五 量化交易全流程( 八 )

< {end_date}"cur.execute(sql)data = http://www.kingceram.com/post/cur.fetchall()data = pd.DataFrame(data)data = data.rename(columns={0:"date", 1: "stock_code", 2: "open", 3: "high", 4: "low", 5: "close", 6: "volume"})stock_data = http://www.kingceram.com/post/self.data_convert(data)cur.close()conn.close()return stock_datadef candlestick(self, candlestick_df):# 画蜡烛图df = self.convert_date(candlestick_df)# 去除非交易日的间隔ohlc = df[['date','open','high','low','close']]ohlc.loc[:,'date'] = range(len(ohlc))# 重新赋值横轴数据 , 使横轴数据为连续数值# 绘图f1, ax = plt.subplots(figsize = (6,4))candlestick_ohlc(ax, ohlc.values.tolist(), width=.7, colorup='red', colordown='green')plt.xticks(rotation = 30)# 日期显示的旋转角度plt.title(stock_code,fontsize = 14)# 设置图片标题plt.xlabel('日 期',fontsize = 14)# 设置横轴标题plt.ylabel('价 格(元)',fontsize = 14)# 设置纵轴标题date_list = ohlc.index.tolist()# 获取日期列表xticks_len = round(len(date_list)/(len(ax.get_xticks())-1))# 获取默认横轴标注的间隔xticks_num = range(0,len(date_list),xticks_len)# 生成横轴标注位置列表xticks_str = list(map(lambda x:date_list[int(x)],xticks_num))# 生成正在标注日期列表ax.set_xticks(xticks_num)# 设置横轴标注位置ax.set_xticklabels(xticks_str)# 设置横轴标注日期plt.show()def sma(self, sma_df):# 移动均线策略# 两条均线的参数sma_df = sma_df.drop(columns=['date'])df = sma_df.reset_index()df = df[['date','open','high','low','close']]# 使用talib计算移动均线df['ma1'] = ta.SMA(df.close.values, timeperiod = self.L1)df['ma2'] = ta.SMA(df.close.values, timeperiod = self.L2)# 定义多头空头趋势con_long = df['ma1']> df['ma2']con_short = df['ma1'] < df['ma2']# 计算趋势 。0代表没有趋势 , 1代表多头趋势 , -1代表空头趋势df['trend'] = 0df.loc[con_long,'trend'] = 1df.loc[con_short,'trend'] = -1# 假设出现信号后 , 第二天开盘进行交易 , 每次开仓1手(即100股)df['pos'] = 100 * df['trend'].shift(1)# 计算旧仓位和新仓位df['new_pos'] = df['pos'] - df['pos'].shift(1)df['old_pos'] = df['pos'] - df['new_pos']# 把开盘价作为交易价格df['entry_p'] = df['open']# 计算旧仓位的盈利和新仓位的盈利df['p&l_new'] = (df['close'] - df['entry_p']) * df['new_pos']df['p&l_old'] = (df['close'] - df['close'].shift(1)) * df['old_pos']# 每日盈亏由两部分组成df['p&l'] = df['p&l_new'] + df['p&l_old']# 计算累计盈亏df['p&l_cum'] = df['p&l'].cumsum()# 计算净值曲线 , 假设初始资金是1000000ini_cap=1000000df['capital'] = df['p&l_cum'] + ini_capdf['net_value'] = df['capital'] / ini_cap# 绘制净值曲线df = df.set_index('date')df.plot(figsize=(6,4), y=['net_value'])import matplotlib.pyplot as pltplt.xticks(rotation=30)plt.show()sd = StockData(3,7)stock_code = '600519'start_date = '20230104'end_date = '20230904'stock_dt = sd.get_stock_data(stock_code, start_date, end_date)print(stock_dt)sd.candlestick(stock_dt)sd.sma(stock_dt)
结果如图:
通过这个例子 , 我们可以看到 , 回测其实就是从策略逻辑开始 , 逐步求出策略的表现 。策略表现有很多种形式 , 比如每日盈亏、累计盈亏、净值曲线等 。在实际应用中 , 我们不一定需要求出每一个统计值 , 往往只需要求出最需要的那个统计值就可以了 。比如 , 我就经常只求到每日盈亏 , 就直接计算夏普比率 , 这样不用考虑初始资金 , 可以充分简化问题 。这也是自己写回测的最大好处 , 方便又灵活 。