def _get_df_factor(self): begin_date = ps.shift_n_trading_day(str(self.begin_year) + '0101', n=1) self._df_factor = ps.pickle_read(self._ts_data_path + 'df_factor.pkl') self._df_factor = self._df_factor.loc[begin_date:] if self.cut_small == True: self._df_factor = self._df_factor.groupby( level=0, group_keys=False).apply(lambda x: x.loc[x[ 'circ_mv'] > x['circ_mv'].quantile(0.3), :])
def _get_pos_hold(self): self.large_high_pos = {} self.small_high_pos = {} self.large_low_pos = {} self.small_low_pos = {} for month_date in sorted(list(self.context.df_ret_dict.keys())): buy_date = ps.shift_n_trading_day(month_date, -1) self.large_high_pos[buy_date], self.small_high_pos[buy_date], self.large_low_pos[buy_date], self.small_low_pos[buy_date] =\ self._cal_factor_pos(month_date)
def _cal_ret(self, pos_hold_raw): ret_list = [] turnover_dict = {} delist_turnover_dict = {} pos_hold = pos_hold_raw.copy() rebalance_dates = sorted(list(pos_hold.keys())) for i, date in enumerate(rebalance_dates): pre_date = ps.shift_n_trading_day(date) df = pd.merge(pos_hold[date].to_frame(), self.context.df_ret_dict[pre_date].iloc[:, 1:], left_index=True, right_index=True, how='left').fillna(0) ret = df.iloc[:, 1:].apply(np.average, weights=df.iloc[:, 0]) if i == 0: ret = ret.append(pd.Series(index=[date], data=0)) turnover_dict[date] = 1.0 if i < len(rebalance_dates) - 1: nav_end = df.iloc[:, 1:].multiply(df.iloc[:, 0], axis=0).add(1).prod(axis=1) wgt_end = nav_end / nav_end.sum() cannot_sell_stock = self.context.cannot_sell_dict[ df.iloc[:, -1].name] delist_stock = self.context.delist_stock_dict[df.iloc[:, -1].name] delist_stock = set(cannot_sell_stock).intersection( set(delist_stock)) if len(delist_stock) != 0: cannot_sell_stock = set(cannot_sell_stock) - set( delist_stock) delist_turnover = wgt_end.loc[wgt_end.index.isin( delist_stock)].sum() else: delist_turnover = 0 delist_turnover_dict[date] = delist_turnover wgt_cannot_sell = wgt_end.loc[wgt_end.index.isin( cannot_sell_stock)] origin_pos = pos_hold[df.iloc[:, -1].name] new_pos = (1 - wgt_cannot_sell.sum()) * origin_pos new_pos = new_pos.append(wgt_cannot_sell).groupby( level=0).sum() pos_hold[df.iloc[:, -1].name] = new_pos turnover_rate = pd.merge( wgt_end.to_frame(), new_pos.to_frame(), left_index=True, right_index=True, how='outer').fillna(0).diff(axis=1).abs().sum().iloc[-1] ret_list.append(ret) turnover_dict[df.iloc[:, -1].name] = turnover_rate else: ret_list.append(ret) res = pd.concat(ret_list, axis=0).sort_index(ascending=True) df_turnover = pd.Series(turnover_dict) df_delist_turnover = pd.Series(delist_turnover_dict) return res, df_turnover, df_delist_turnover
def _get_cannot_sell_dict(self): begin_date = ps.shift_n_trading_day(str(self.begin_year) + '0131', n=-1) self._cannot_sell_dict = ps.pickle_read(self._ts_data_path + 'cannot_sell_stock.pkl') self._cannot_sell_dict = self._cannot_sell_dict.loc[begin_date:] if self.cannot_sell: pass else: for date in self._cannot_sell_dict.index(): self._cannot_sell_dict[date] = []
def _cal_factor_pos(self, date): if self.context.factor_name == 'circ_mv': df = self.context.df_factor.loc[date][[ self.context.factor_name, self.cut_item ]].dropna(axis=0, how='any') df['bp'] = 1 / df[self.cut_item] del df[self.cut_item] df['mv_cut'] = pd.qcut(df['circ_mv'], 2, ['small', 'large']) df['factor_cut'] = None df.loc[df['mv_cut'] == 'small', 'factor_cut'] = pd.qcut(df.loc[df['mv_cut'] == 'small', 'bp'], [0, 0.3, 0.7, 1], ['low', 'medium', 'high']) df.loc[df['mv_cut'] == 'large', 'factor_cut'] = pd.qcut(df.loc[df['mv_cut'] == 'large', 'bp'], [0, 0.3, 0.7, 1], ['low', 'medium', 'high']) buy_date = ps.shift_n_trading_day(date, n=-1) df = df.loc[list( set(df.index.tolist()) - set(self.context.cannot_buy_dict[buy_date]))] df_large_high = df.query('mv_cut=="large" and factor_cut=="high"') df_small_high = df.query('mv_cut=="small" and factor_cut=="high"') df_large_low = df.query('mv_cut=="large" and factor_cut=="low"') df_small_low = df.query('mv_cut=="small" and factor_cut=="low"') df_large_medium = df.query('mv_cut=="large" and factor_cut=="medium"') df_small_medium = df.query('mv_cut=="small" and factor_cut=="medium"') if self.context.weighted_method == 'eql_weighted': def cal_weight(df): return pd.Series(index=df.index, name='eql_weighted').fillna(1 / len(df)) return cal_weight(df_large_high), cal_weight( df_small_high), cal_weight(df_large_low), cal_weight( df_small_low), cal_weight(df_large_medium), cal_weight( df_small_medium) if self.context.weighted_method == 'mv_weighted': def cal_weight(df): return df['circ_mv'] / df['circ_mv'].sum() return cal_weight(df_large_high), cal_weight( df_small_high), cal_weight(df_large_low), cal_weight( df_small_low), cal_weight(df_large_medium), cal_weight( df_small_medium)
def _get_df_ret_dict(self): begin_date = ps.shift_n_trading_day(str(self.begin_year) + '0101', n=1) self._df_ret_dict = ps.pickle_read(self._ts_data_path + 'df_ret.pkl') self._df_ret_dict = self._df_ret_dict.loc[begin_date:]
def _get_delist_stock_dict(self): begin_date = ps.shift_n_trading_day(str(self.begin_year) + '0131', n=-1) self._delist_stock_dict = ps.pickle_read(self._ts_data_path + 'delist_stock.pkl') self._delist_stock_dict = self._delist_stock_dict.loc[begin_date:]
def _get_cannot_buy_dict(self): begin_date = ps.shift_n_trading_day(str(self.begin_year) + '0101', n=-1) self._cannot_buy_dict = ps.pickle_read(self._ts_data_path + 'cannot_buy_stock.pkl') self._cannot_buy_dict = self._cannot_buy_dict.loc[begin_date:]
def _get_pos_hold(self): self.mkt_pos = {} for month_date in sorted(list(self.context.df_ret_dict.keys())): buy_date = ps.shift_n_trading_day(month_date, -1) self.mkt_pos[buy_date] = self._cal_factor_pos(month_date)