量化交易9-backtrader回测十字星K线形态图

十字星形态图,在股市中的应用:
十字星是一种K线基本型态 。十字星,是一种只有上下影线,没有实体的K线图 。开盘价即是收盘价,表示在交易中,股价出现高于或低于开盘价成交,但收盘价与开盘价相等 。其中:上影线越长,表示卖压越重 。下影线越长,表示买盘旺盛 。通常在股价高位或低位出现十字线,可称为转机线,意味着出现反转 。
以上的文字笔者截取自百度百科,笔者对以上的定义做个解读:十字星作为反转形态出现,出现在底部那么就会上涨,出现在顶部,那么就会下跌,根据这个解读,就得出一个策略:底部十字星,全仓买入,顶部十字星,全仓卖出 。
综上:今天笔者要回测的策略为:底部十字星,全仓买入,顶部十字星,全仓卖出
先上代码和结论:

量化交易9-backtrader回测十字星K线形态图

文章插图
import tushare as tsimport pandas as pdimport datetime# For datetime objectsimport os.path# To manage pathsimport sys# To find out the script name (in argv[0])# Import the backtrader platformimport backtrader as btimport talib as talibimport numpy as npclass MyStrategy(bt.Strategy):# 策略参数params = dict(printlog=False)def __init__(self):self.star = dict()# 定义全局变量self.count = 0for data in self.datas:# 转为tabib要求的数据格式opens = np.array(data.open.array)highs = np.array(data.high.array)lows = np.array(data.low.array)closes = np.array(data.close.array)print(opens)# 计算十字星数据,结果为-100底部十字星,结果为100顶部十字星,0非十字星res = talib.CDLDOJISTAR(opens, highs, lows, closes)# 数据放入self中self.star[data._id] = resdef next(self):# 得到当前的账户价值total_value = http://www.kingceram.com/post/self.broker.getcash()for data in self.datas:pos = self.getposition(data).size# 函数出现100就代表出现十字星形态,做买入if total_value> 0 and self.star[data._id][self.count] == -100:p_value = http://www.kingceram.com/post/total_value * 0.9 / 10size = ((int(total_value / self.data.close[0]))) - ((int(total_value / self.data.close[0])) % 100) - 100self.buy(data=data, size=size)print('出现底部十字星,全仓买入,买入数量' + str(size) )# 买入后的出现顶部十字星全仓后卖出if pos> 0 and self.star[data._id][self.count] == 100:# 全部卖出# 跟踪订单避免重复self.sell(data=http://www.kingceram.com/post/data, size=pos)print('出现顶部十字星,卖出数量' + str(pos) )#自增处理self.count = self.count + 1def 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.size:.2f},/手续费:{order.executed.comm:.2f}')self.buyprice = order.executed.priceself.buycomm = order.executed.commelse:self.log(f'卖出:/n价格:{order.executed.price:.2f},/成本: {order.executed.value:.2f},/数量:{order.executed.size:.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:returnself.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 = '20190101'# end_dt=''print(code, start_dt, end_dt)data = http://www.kingceram.com/post/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'] = 0data['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'] = 0data = bt.feeds.PandasData(dataname=dataframe,fromdate=datetime.datetime(2008, 2, 20),todate=datetime.datetime(2022, 4, 5))cerebro.adddata(data)# 回测设置startcash = 100000.0cerebro.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()