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
예제 #6
0
    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
예제 #7
0
    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