def out_sample_perf(pnl_df_out, way=1, cut_point_list=None): # 根据sharpe大小,统计样本外的表现 if cut_point_list is None: cut_point_list = [0.30] if way == 1: rolling_sharpe, cut_sharpe = \ bt.AZ_Rolling_sharpe(pnl_df_out, roll_year=0.5, year_len=250, cut_point_list=cut_point_list, output=True) else: rolling_sharpe, cut_sharpe = \ bt.AZ_Rolling_sharpe(-pnl_df_out, roll_year=0.5, year_len=250, cut_point_list=cut_point_list, output=True) sharpe_quantile = cut_sharpe.values[0] out_condition = sharpe_quantile > 0.8 return out_condition, round(sharpe_quantile * way, 4)
def filter_all(cut_date, pos_df_daily, pct_n, if_return_pnl=False, if_only_long=False): if if_only_long: pnl_df = (pos_df_daily[pos_df_daily > 0] * pct_n).sum(axis=1) pnl_df = pnl_df.replace(np.nan, 0) else: pnl_df = (pos_df_daily * pct_n).sum(axis=1) pnl_df = pnl_df.replace(np.nan, 0) # pnl_df = pd.Series(pnl_df) # 样本内表现 return_in = pct_n[pct_n.index < cut_date] pnl_df_in = pnl_df[pnl_df.index < cut_date] asset_df_in = pnl_df_in.cumsum() last_asset_in = asset_df_in.iloc[-1] pos_df_daily_in = pos_df_daily[pos_df_daily.index < cut_date] pot_in = AZ_Pot(pos_df_daily_in, last_asset_in) leve_ratio = AZ_Leverage_ratio(asset_df_in) if leve_ratio < 0: leve_ratio = 100 sharpe_q_in_df = bt.AZ_Rolling_sharpe(pnl_df_in, roll_year=1, year_len=250, min_periods=1, cut_point_list=[0.3, 0.5, 0.7], output=False) sp_in = bt.AZ_Sharpe_y(pnl_df_in) fit_ratio = bt.AZ_fit_ratio(pos_df_daily_in, return_in) ic = round( bt.AZ_Normal_IC(pos_df_daily_in, pct_n, min_valids=None, lag=0).mean(), 6) sharpe_q_in_df_u, sharpe_q_in_df_m, sharpe_q_in_df_d = sharpe_q_in_df.values in_condition_u = sharpe_q_in_df_u > 0.9 and leve_ratio > 1 in_condition_d = sharpe_q_in_df_d < -0.9 and leve_ratio > 1 # 分双边和只做多 if if_only_long: in_condition = in_condition_u else: in_condition = in_condition_u | in_condition_d if sharpe_q_in_df_m > 0: way = 1 else: way = -1 # 样本外表现 pnl_df_out = pnl_df[pnl_df.index >= cut_date] out_condition, sharpe_q_out = out_sample_perf_c(pnl_df_out, way=way) if if_return_pnl: return in_condition, out_condition, ic, sharpe_q_in_df_u, sharpe_q_in_df_m, sharpe_q_in_df_d, pot_in, \ fit_ratio, leve_ratio, sp_in, sharpe_q_out, pnl_df else: return in_condition, out_condition, ic, sharpe_q_in_df_u, sharpe_q_in_df_m, sharpe_q_in_df_d, pot_in, \ fit_ratio, leve_ratio, sp_in, sharpe_q_out
def filter_pot_sharpe(cut_date, signal, pct_n, index_df, lag=1, hold_time=5, if_hedge=True, hedge_ratio=1, if_return_pnl=False): # signal向下移动一天,避免未来函数 signal = signal.shift(lag) # # 将所有的0替换为nan,使得计算ic时更加合理, 计算pnl时没影响 # signal = signal.replace(0, np.nan) pos_df_daily = pos_daily_fun(signal, n=hold_time) if if_hedge: hedge_df = hedge_ratio * index_df.mul(pos_df_daily.sum(axis=1), axis=0) # pnl_df = (signal * pct_n).sum(axis=1).sub(hedge_df, axis=0) pnl_df = -hedge_df.sub((pos_df_daily * pct_n).sum(axis=1), axis=0) pnl_df = pnl_df[pnl_df.columns[0]] else: pnl_df = (pos_df_daily * pct_n).sum(axis=1) # pnl_df = pd.Series(pnl_df) # 样本内表现 pnl_df_in = pnl_df[pnl_df.index < cut_date] asset_df_in = pnl_df_in.cumsum() last_asset_in = asset_df_in.iloc[-1] pos_df_daily_in = pos_df_daily[pos_df_daily.index < cut_date] pot = AZ_Pot(pos_df_daily_in, last_asset_in) sharpe_q_in_df = bt.AZ_Rolling_sharpe(pnl_df_in, roll_year=1, year_len=250, min_periods=1, cut_point_list=[0.3, 0.5, 0.7], output=False) sharpe_q_in_df_u, sharpe_q_in_df_m, sharpe_q_in_df_d = sharpe_q_in_df.values in_condition_u = sharpe_q_in_df_u > 0.9 in_condition_d = sharpe_q_in_df_d < -0.9 in_condition = in_condition_u | in_condition_d if sharpe_q_in_df_m > 0: way = 1 else: way = -1 # 样本外表现 pnl_df_out = pnl_df[pnl_df.index >= cut_date] out_condition, sharpe_q_out = out_sample_perf(pnl_df_out, way=way) if if_return_pnl: return in_condition, out_condition, sharpe_q_in_df_u, sharpe_q_in_df_m, sharpe_q_in_df_d, pot, sharpe_q_out, \ pnl_df else: return in_condition, out_condition, sharpe_q_in_df_u, sharpe_q_in_df_m, sharpe_q_in_df_d, pot, sharpe_q_out
def filter_time_para_fun(time_para_dict, pos_df_daily, adj_return, if_return_pnl, if_only_long): if if_only_long: pnl_df = (pos_df_daily[pos_df_daily > 0] * adj_return).sum(axis=1) pnl_df = pnl_df.replace(np.nan, 0) else: pnl_df = (pos_df_daily * adj_return).sum(axis=1) pnl_df = pnl_df.replace(np.nan, 0) result_dict = OrderedDict() for time_key in time_para_dict.keys(): begin_para, cut_para, end_para_1, end_para_2, end_para_3, end_para_4 = time_para_dict[ time_key] # 样本内索引 sample_in_index = (adj_return.index >= begin_para) & (adj_return.index < cut_para) # 样本外索引 sample_out_index_1 = (adj_return.index >= cut_para) & (adj_return.index < end_para_1) sample_out_index_2 = (adj_return.index >= cut_para) & (adj_return.index < end_para_2) sample_out_index_3 = (adj_return.index >= cut_para) & (adj_return.index < end_para_3) sample_out_index_4 = (adj_return.index >= cut_para) & (adj_return.index < end_para_4) # 样本内表现 pos_df_daily_in = pos_df_daily[sample_in_index] if len(pos_df_daily_in.abs().sum(axis=1).replace( 0, np.nan).dropna()) / len(pos_df_daily_in) < 0.1: continue adj_return_in = adj_return[sample_in_index] pnl_df_in = pnl_df[sample_in_index] asset_df_in = pnl_df_in.cumsum() last_asset_in = asset_df_in.iloc[-1] pot_in = AZ_Pot(pos_df_daily_in, last_asset_in) leve_ratio = AZ_Leverage_ratio(asset_df_in) if leve_ratio < 0: leve_ratio = 100 sharpe_q_in_df = bt.AZ_Rolling_sharpe(pnl_df_in, roll_year=1, year_len=250, min_periods=1, cut_point_list=[0.3, 0.5, 0.7], output=False) sharpe_q_in_df = round(sharpe_q_in_df, 4) sp_in = bt.AZ_Sharpe_y(pnl_df_in) fit_ratio = bt.AZ_fit_ratio(pos_df_daily_in, adj_return_in) ic = round( bt.AZ_Normal_IC(pos_df_daily_in, adj_return_in, min_valids=None, lag=0).mean(), 6) sp_in_u, sp_in_m, sp_in_d = sharpe_q_in_df.values in_condition_u = sp_in_u > 0.9 and leve_ratio > 1 in_condition_d = sp_in_d < -0.9 and leve_ratio > 1 # 分双边和只做多 if if_only_long: in_condition = in_condition_u else: in_condition = in_condition_u | in_condition_d if sp_in_m > 0: way = 1 else: way = -1 # 样本外表现 pnl_df_out_1 = pnl_df[sample_out_index_1] pnl_df_out_2 = pnl_df[sample_out_index_2] pnl_df_out_3 = pnl_df[sample_out_index_3] pnl_df_out_4 = pnl_df[sample_out_index_4] out_condition_1, sp_out_1 = out_sample_perf_c(pnl_df_out_1, way=way) out_condition_2, sp_out_2 = out_sample_perf_c(pnl_df_out_2, way=way) out_condition_3, sp_out_3 = out_sample_perf_c(pnl_df_out_3, way=way) out_condition_4, sp_out_4 = out_sample_perf_c(pnl_df_out_4, way=way) if if_return_pnl: result_dict[time_key] = [ in_condition, out_condition_1, out_condition_2, out_condition_3, out_condition_4, ic, sp_in_u, sp_in_m, sp_in_d, pot_in, fit_ratio, leve_ratio, sp_in, sp_out_1, sp_out_2, sp_out_3, sp_out_4, pnl_df ] else: result_dict[time_key] = [ in_condition, out_condition_1, out_condition_2, out_condition_3, out_condition_4, ic, sp_in_u, sp_in_m, sp_in_d, pot_in, fit_ratio, leve_ratio, sp_in, sp_out_1, sp_out_2, sp_out_3, sp_out_4 ] return result_dict