def Momentum021(cls, data: pd.DataFrame, price: str = PVN.CLOSE.value, n: int = 1): """ 最低价格时间因子(LT):1-index(Min(P, N))/L """ factor_name = sys._getframe().f_code.co_name + f'_{n}days' data.set_index([KN.TRADE_DATE.value, KN.STOCK_ID.value], inplace=True) data.sort_index(inplace=True) data[factor_name] = data[price].groupby(KN.STOCK_ID.value, group_keys=False).rolling(n).apply( lambda x: 1 - (list(x).index(np.nanmin(x)) - 1) / len(x)) F = DataInfo() F.data = data[factor_name] F.data_type = 'MTM' F.data_category = cls().__class__.__name__ F.data_name = factor_name return F
def Momentum006(cls, data: pd.DataFrame, close_price: str = PVN.CLOSE.value, n: int = 1): """ 最高价格因子(HPTP):Max(P,N) / P """ factor_name = sys._getframe().f_code.co_name + f'_{n}days' data.set_index([KN.TRADE_DATE.value, KN.STOCK_ID.value], inplace=True) data.sort_index(inplace=True) data[factor_name] = data[close_price].groupby(KN.STOCK_ID.value, group_keys=False).apply( lambda x: x.rolling(n, min_periods=1).max() / x) F = DataInfo() F.data = data[factor_name] F.data_type = 'MTM' F.data_category = cls().__class__.__name__ F.data_name = factor_name return F
def Momentum013(cls, data: pd.DataFrame, close_price: str = PVN.CLOSE.value, n: int = 1) -> DataInfo: """ 动量CTC收益率(MTM_CTC):N日收盘价计算的收益率均值 :return: """ factor_name = sys._getframe().f_code.co_name + f'_{n}days' data.set_index([KN.TRADE_DATE.value, KN.STOCK_ID.value], inplace=True) data.sort_index(inplace=True) data['return'] = data[close_price].groupby(KN.STOCK_ID.value).pct_change() data[factor_name] = data['return'].groupby(KN.STOCK_ID.value, group_keys=False).rolling(n, min_periods=1).mean() F = DataInfo() F.data = data[factor_name] F.data_type = 'MTM' F.data_category = cls().__class__.__name__ F.data_name = factor_name return F
def Momentum020(cls, data: pd.DataFrame, low_price: str = PVN.LOW.value, high_price: str = PVN.HIGH.value, open_price: str = PVN.OPEN.value, close_price: str = PVN.CLOSE.value, n: int = 1) -> DataInfo: """ 动量CTHL收益率绝对值均值(MTM_CTHL_abs) :return: """ factor_name = sys._getframe().f_code.co_name + f'_{n}days' data.set_index([KN.TRADE_DATE.value, KN.STOCK_ID.value], inplace=True) data.sort_index(inplace=True) data['return_H'] = data.groupby(KN.STOCK_ID.value, group_keys=False).apply(lambda x: (x[high_price] / x[close_price].shift(1) - 1)) data['return_L'] = data.groupby(KN.STOCK_ID.value, group_keys=False).apply(lambda x: (x[low_price] / x[close_price].shift(1) - 1)) data['return_O'] = data.groupby(KN.STOCK_ID.value, group_keys=False).apply(lambda x: (x[open_price] / x[close_price].shift(1) - 1)) data_sub_H = data[data['return_O'] > 0]['return_H'] data_sub_L = data[data['return_O'] < 0]['return_L'] data_sub_O = data[data['return_O'] == 0]['return_O'] data["CTHL"] = pd.concat([abs(data_sub_H), abs(data_sub_L), abs(data_sub_O)]) data[factor_name] = data['CTHL'].groupby(KN.STOCK_ID.value, group_keys=False).rolling(n, min_periods=1).mean() F = DataInfo() F.data = data[factor_name] F.data_type = 'MTM' F.data_category = cls().__class__.__name__ F.data_name = factor_name return F
def Momentum026(cls, data: pd.DataFrame, close_price: str = PVN.CLOSE.value, n: int = 1) -> DataInfo: """ 收益率rank标准差(MTM_RankPrice_std) """ factor_name = sys._getframe().f_code.co_name + f'_{n}days' data.set_index([KN.TRADE_DATE.value, KN.STOCK_ID.value], inplace=True) data.sort_index(inplace=True) data['ret'] = data[close_price].groupby(KN.STOCK_ID.value).pct_change() data['rank'] = data['ret'].groupby(KN.TRADE_DATE.value).rank() data[factor_name] = data['rank'].groupby(KN.TRADE_DATE.value, group_keys=False).rolling(n, min_periods=2).std(ddof=1) F = DataInfo() F.data = data[factor_name] F.data_type = 'MTM' F.data_category = cls().__class__.__name__ F.data_name = factor_name return F
def strategyLabel(self) -> DataInfo: func_name = sys._getframe().f_code.co_name result_path = os.path.join(self.local_path, func_name + '.pkl') if os.path.exists(result_path): with open(result_path, 'rb') as f: category_label = pickle.load(f) else: # read data print( f"{dt.datetime.now().strftime('%X')}: Construction the label pool" ) data_dict = self.read_data() price_data = data_dict['AStockData.csv'][self.Mapping["price"] ['columns']] ind_exp = data_dict['AStockData.csv'][self.Mapping["industry"] ['columns']] stock_mv_data = data_dict['AStockData.csv'][ self.Mapping["mv"]['columns']] * 10000 # wan yuan->yuan # composition_data = data_dict['IndexMember.csv'][self.Mapping['composition']['columns']] stock_w_data = data_dict['StockPool.csv'][self.Mapping['stock_w1'] ['columns']] up_down_limit = data_dict['AStockData.csv'][ self.Mapping['priceLimit']['columns']] price_data = price_data.rename( columns={ PVN.CLOSE_ADJ.value: PVN.CLOSE.value, PVN.OPEN_ADJ.value: PVN.OPEN.value, PVN.HIGH_ADJ.value: PVN.HIGH.value, PVN.LOW_ADJ.value: PVN.LOW.value }) print( f"{dt.datetime.now().strftime('%X')}: Calculate stock daily return label" ) stock_ret_c = self.api.stock_ret(price_data, return_type=PVN.CLOSE.value) stock_ret_o = self.api.stock_ret(price_data, return_type=PVN.OPEN.value) print(f"{dt.datetime.now().strftime('%X')}: Set price limit label") up_down_limit = up_down_limit.fillna(1) == 0 ############################################################################################################ # merge labels print(f"{dt.datetime.now().strftime('%X')}: Merge labels") category_label = self.merge_labels( data_ret_close=stock_ret_c, data_ret_open=stock_ret_o, # composition=composition_data, ind_exp=ind_exp, mv=stock_mv_data[PVN.LIQ_MV.value], stock_w=stock_w_data, price_limit=up_down_limit) # sort category_label = category_label.sort_index() category_label.to_pickle(result_path) dataClass = DataInfo(data=category_label, data_category=self.__class__.__name__, data_name=func_name) return dataClass
def StockPoolZD(self) -> DataInfo: """ 1.剔除ST股:是ST为True 2.剔除成立年限小于6个月的股票:成立年限小于6个月为False 3.过去5天成交额占比排名最后5%:成交额占比在最后5%为False 4.过去5天停牌天数超过3天:停牌数超过阈值为False 注意:函数名需要与数据源文件名对应,保持一致防止出错,可自行修改 :return: """ func_name = sys._getframe().f_code.co_name result_path = os.path.join(self.local_path, func_name + '.pkl') if os.path.exists(result_path): with open(result_path, 'rb') as f: stock_judge = pickle.load(f) else: # read data print( f"{dt.datetime.now().strftime('%X')}: Read the data of stock pool" ) data_input = self.read_data(func_name) # get filter condition print(f"{dt.datetime.now().strftime('%X')}: Weed out ST stock") data_input['judge1'] = self.api.ST(data_input[PVN.ISST.value]) # print(f"{dt.datetime.now().strftime('%X')}: Weed out Price Up_Down limit stock") # data_input['judge2'] = self.price_limit(data_input[PVN.Up_Down.value]) print( f"{dt.datetime.now().strftime('%X')}: Weed out stock Established in less than 6 months" ) data_input['judge3'] = self.api.established( data=data_input[PVN.LIST_DAYS_NUM.value]) print( f"{dt.datetime.now().strftime('%X')}: Weed out stock illiquidity" ) data_input['judge4'] = self.api.liquidity( data_input[PVN.AMOUNT.value]) print( f"{dt.datetime.now().strftime('%X')}: Weed out Suspension stock" ) data_input['judge5'] = self.api.suspension( data_input[PVN.AMOUNT.value]) print( f"{dt.datetime.now().strftime('%X')}: Weed out liq_mv less than 0.02 stock" ) data_input['judge6'] = self.api.liq_mv( data_input[PVN.LIQ_MV.value]) print( f"{dt.datetime.now().strftime('%X')}: Weed out science and technology innovation board stock" ) data_input['judge7'] = self.api.list_board( data_input[PVN.LIST_BOARD.value]) Judge = [ column for column in data_input.columns if 'judge' in column ] # Filter stock_judge = data_input[Judge].all(axis=1).sort_index() stock_judge.name = func_name # to_csv stock_judge.to_pickle(result_path) # switch judge to label stock_pool = stock_judge.groupby( KN.STOCK_ID.value).shift(1).fillna(True) dataClass = DataInfo(data=stock_pool[stock_pool], data_category=self.__class__.__name__, data_name=func_name) return dataClass