# 量化回测作业 **Repository Path**: cheng-guansheng/quantitative-back-testing ## Basic Information - **Project Name**: 量化回测作业 - **Description**: 跟据给定的目标持仓及各品种的主力 1m价格信息,绘制相关图表 - **Primary Language**: Python - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2022-12-02 - **Last Updated**: 2023-04-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 量化回测作业 ## 介绍 根据给定的目标持仓及各品种的主力 1m价格信息,得到相关指标的图表 ## 代码介绍 ### 1.首先建立历史数据表 根据目标持仓来确定需要哪些品类,以及这些品类对于时间段的信息,汇聚在一个DataFrame类中。方便后续的查找遍历计算等操作。并且对表中的NaN进行填充,使用的填充方法为"ffill"避免使用未来数据。相应函数如下: ``` `def build_history_data(SampleTarget): ''' 建立历史数据表 :param SampleTarget: 目标持仓表 :return: 历史数据表 ''' history_data = feather.read_dataframe('1m/a.ft') history_data = history_data[history_data['timestamp'] == 145900] history_data = history_data[['trading_day']] start_day = SampleTarget['trading_day'][0] #将目标持仓表中包含的品种历史数据收集到history_data中 for filename in SampleTarget.columns[2:]: path = '1m/' + filename + '.ft' df = feather.read_dataframe(path) df = df[df['timestamp'] == 145900] df = df[['trading_day', 'clz']] df.columns = ['trading_day', filename] history_data = history_data.merge(df, how='left', on='trading_day') history_data = history_data[history_data['trading_day'] >= start_day] #使用ffill向前填充,对Nan进行处理 history_data.fillna(method='ffill', axis=0) history_data.fillna(0) return history_data` ``` ### 2.计算相关指标 #### 每日pnl矩阵 每日pnl矩阵的计算逻辑为先某品类价格实际变化率chg,具体方式是用后一天的价格减去前一天的价格再除以前一天的价格,之后再用已持仓的金额乘以这个比例即可得到这一天的pnl具体函数如下: ``` def cul_total_pnl(history_data, SampleTarget): ''' 计算全品类的pnl :param history_data: 历史数据 :param SampleTarget: 目标持仓表 :return: 总pnl矩阵 ''' #计算相应期货价格的变化率 chg = (history_data.shift(-1) - history_data)/history_data #用变化率乘持仓得到pnl值 pnl = chg[chg.columns[1:]] * SampleTarget[SampleTarget.columns[2:]] return pnl.iloc[:SampleTarget.shape[0]] ``` 相应的也可以计算某一个品类的pnl值,只需要在pnl矩阵中取相应的列即可 ``` def cul_pnl(pnl, name): ''' 用于计算某一品种的pnl值,并画出图像 :param pnl: 全品种的每日pnl数据 :param name: 对应品种的名字 :return: 单一品种的累计pnl ''' cur_pnl = pnl[name] cum_pnl = cur_pnl.cumsum() plt.plot(cum_pnl) return cum_pnl ``` #### sharp值 这里使用的sharp计算公式为 pnl 均值 / pnl 标准差* 15.8 ``` def cul_sharp(pnl): ''' 计算夏普值 :param pnl: 总的日pnl矩阵 :return: sharp ''' # new_pnl = pnl.sum(axis=1) sharp = np.mean(new_pnl) / np.std(new_pnl) * 15.8 return sharp ``` #### 每日成交额 每日成交额的计算方法为,用目前持仓的价值 - 第二天的目标持仓这样就可以得到交易额,正数表示套现的钱,负数表示支出的钱 ``` def cul_turnover(history_data, SampleTarget): ''' 计算每天的成交金额 :param history_data: :param SampleTarget: :return: 日成交金额 ''' chg = (history_data.shift(-1) - history_data)/history_data # 使用持仓价值 - 目标持仓的价值得到日换手金额 turnover = (chg + 1)[chg.columns[1:]] * SampleTarget[SampleTarget.columns[2:]] - SampleTarget.shift(-1)[SampleTarget.columns[2:]] #减去手续费 turnover = turnover - abs(turnover)*0.0003 #计算全部品种的日换手金额 turnover = turnover.sum(axis=1) return turnover.iloc[:SampleTarget.shape[0]] ``` #### AvgLeverage AvgLeverage的计算方法为全品种平均仓位 / 初始资金 ``` def cul_AvgLeverage(SampleTarget, initmount): ''' :param SampleTarget: :param initmount: :return: ''' AvgLeverage = SampleTarget[SampleTarget.columns[2:]].sum(axis=1) AvgLeverage = AvgLeverage[len(AvgLeverage)-1] / initmount return AvgLeverage ``` ### 3.主函数(绘制相关图像) 绘制相关图像时使用累计值,首先判断初始金额,对于计算出来的pnl以及turnover值使用cumsum()函数来计算累计值,并绘制函数 ``` if __name__ == "__main__": # 获取目标仓位表 SampleTarget = pd.read_csv('SampleTarget1.csv') SampleTarget.fillna(method='ffill', axis=0) SampleTarget.fillna(0) # 判断初始金额 if max(SampleTarget[SampleTarget.columns[2:]].iloc[0]) < 100: InitMount = 1 else: InitMount = 1000000 #获取历史数据 history_data = build_history_data(SampleTarget) #pnl的累计量用于画图 pnl = cul_total_pnl(history_data, SampleTarget) pnl_cum = pnl.sum(axis=1).cumsum() #计算turnover的累计值用于画图 turnover = cul_turnover(history_data, SampleTarget) turnover_cum = turnover.cumsum() #计算总TurnOver TurnOver = turnover_cum[len(turnover) - 1] / InitMount #计算sharp值 sharp = cul_sharp(pnl) #计算AvgLeverage AvgLeverage = cul_AvgLeverage(SampleTarget, InitMount) #绘制图像 data = list(SampleTarget['trading_day'].astype('str')) plt.figure(figsize=(12,4)) plt.plot(data, pnl_cum, 'r-', label='pnl') plt.plot(data, turnover_cum, 'b-', label='turnover') x_major_locator = MultipleLocator(500) ax = plt.gca() ax.xaxis.set_major_locator(x_major_locator) plt.legend() plt.title("Sharp=%f" %sharp + ' TurnOver=%f'%TurnOver + ' AvgLeverage=%f' %AvgLeverage) ``` ## 结果展示 ![输入图片说明](Figure_1.png) ![输入图片说明](Figure_2.png) ![输入图片说明](Figure_3.png) ![输入图片说明](Figure_4.png)