# 期货回测实现 **Repository Path**: axelors/2022_backtest ## Basic Information - **Project Name**: 期货回测实现 - **Description**: 2022年大作业,对期货进行回测实现 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2022-12-05 - **Last Updated**: 2024-04-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 期货数据回测 计算思路: 1、 计算每天145900的持仓市值,根据市值变化计算pnl 2、 计算每次调仓前后市值的变化计算turnover 3、 用pnl-每天发生的turnover*交易费率计算pnl-net 一、读取每次交易对应的clz,如果交易对应timestamp的clz字段缺失,则使用之前最近的clz: 1. for name in path_ft_ls: 2. # name = path_ft_ls[0] 3. df_t = pd.read_feather('1m/1m/' + name + '.ft') 4. df_t = df_t.merge(df_clz[['trading_day', 'timestamp']], on=['trading_day'], how='left', suffixes=('', '_clz')) 5. df_t = df_t[df_t['timestamp'] <= df_t['timestamp_clz']] 6. df_t = df_t.groupby(by=['trading_day', 'timestamp_clz'])[['clz']].last() 7. df_t.reset_index(inplace=True) 8. df_t.rename(columns={'timestamp_clz':'timestamp', 'clz': name}, inplace=True) 9. df_clz = df_clz.merge(df_t[['trading_day', 'timestamp', name]], on=['trading_day', 'timestamp'], how='left') 二、读取每天145900结算的clz,同理如果145900的clz缺失,则使用之前最近的clz: 1. df_clz_1459 = pd.DataFrame() 2. df_clz_1459['trading_day'] = df_tar['trading_day'] 3. df_clz_1459['timestamp'] = 145900 4. for name in path_ft_ls: 5. # name = path_ft_ls[0] 6. df_t = pd.read_feather('1m/1m/' + name + '.ft') 7. df_t = df_t.groupby(by=['trading_day'])[['clz']].last() 8. df_t.rename(columns = {'clz':name},inplace=True) 9. # df_clz_1459[name] = df_t['clz'] 10. df_clz_1459 = df_clz_1459.merge(df_t, on=['trading_day'], how='left') 三、将各个表格的trading-day设置为index 1. def SetTimeIndex(df_tar): 2. df_tar.loc[df_tar['timestamp'] > 145900, 'trading_day'] = df_tar.shift(-1)[df_tar['timestamp'] > 145900]['trading_day'].values 3. df_tar.set_index(keys=['trading_day'], inplace=True) 4. df_tar.index = pd.DatetimeIndex(df_tar.index.astype(int).astype(str)) 5. df_tar.drop(labels=['timestamp'], inplace=True, axis=1) 6. return df_tar 7. df_tar = SetTimeIndex(df_tar) 8. df_clz = SetTimeIndex(df_clz) 9. df_clz_1459 = SetTimeIndex(df_clz_1459) 1. df_clz_1459 = df_clz_1459.loc[df_tar.index] 2. 3. df_clz_1459 = df_clz_1459.loc[~df_clz_1459.index.duplicated(keep='last')] 4. df_tar_last = df_tar.loc[~df_tar.index.duplicated(keep='last')] 数据说明: df_tar:详细的每一笔交易target df_clz:详细的每一笔交易clz df_clz_1459:每天145900时的clz df_tar_last:每天145900前最后的target状态 四、由于timestamp可能会超过结算时间145900,超过的行,对应的trading-day应该被更改为下一个target对应的交易日期: 1. df_tar.loc[df_tar['timestamp'] > 145900, 'trading_day'] = df_tar.shift(-1)[df_tar['timestamp'] > 145900]['trading_day'].values 用df_clz_1459、df_tar_last计算pnl;用df_tar、df_clz计算turnover,然后对turnover做天的加总;用pnl_net = pnl - turnover*3*10**(-4)计算pnl_net: 1. pnl = (df_tar_last.shift(1)*df_clz_1459/df_clz_1459.shift(1) - df_tar_last.shift(1)).sum(axis = 1) 2. 3. turnover = (df_tar - df_tar.shift(1)*df_clz/df_clz.shift(1)).abs().sum(axis = 1) 4. turnover = turnover.groupby(by=['trading_day']).last() 5. 6. pnl_net = pnl - turnover*3*10**(-4) 五、计算夏普、换手、平均杠杆率: 1. Sharp = pnl_net.mean() / pnl_net.std() * 15.8 2. lower = 1 3. if df_tar.iloc[0, :].sum() > 5: 4. lower = 100e4 5. TurnOver = turnover.mean() / lower 6. AveLeverage = df_tar.sum(axis = 1).abs().mean() / lower 六、作图: 1. plt.figure('pnl') 2. plt.title('Sharp:{:.2f},TurnOver:{:.2f},AveLeverage:{:.2f}'.format(Sharp, TurnOver, AveLeverage)) 3. plt.plot(pnl.cumsum(), label = 'pnl') 4. plt.plot(pnl_net.cumsum(), label = 'pnl_net') 5. plt.legend() 6. plt.show()