Esempio n. 1
0
    def compute(self, begin_date=None, end_date=None):
        """
        计算指定时间段内所有股票的该因子的值,并保存到数据库中
        :param begin_date:  开始时间
        :param end_date: 结束时间
        """
        dm = DataModule()

        # 如果没有指定日期范围,则默认为计算当前交易日的数据
        if begin_date is None:
            begin_date = datetime.now().strftime('%Y-%m-%d')

        if end_date is None:
            end_date = datetime.now().strftime('%Y-%m-%d')

        dates = get_trading_dates(begin_date, end_date)

        for date in dates:
            # 查询出股票在某一交易日的总股本
            df_basics = dm.get_stock_basic_at(date)

            if df_basics.index.size == 0:
                continue

            # 将索引改为code
            df_basics.set_index(['code'], 1, inplace=True)

            # 查询出股票在某一个交易日的收盘价
            df_dailies = dm.get_one_day_k_data(autype=None, date=date)

            if df_dailies.index.size == 0:
                continue

            # 将索引设为code
            df_dailies.set_index(['code'], 1, inplace=True)

            update_requests = []
            for code in df_dailies.index:
                try:
                    # 股价
                    close = df_dailies.loc[code]['close']
                    # 总股本
                    total_shares = df_basics.loc[code]['totals']
                    # 总市值 = 股价 * 总股本
                    total_capital = round(close * total_shares, 2)

                    print('%s, %s, mkt_cap: %15.2f' %
                          (code, date, total_capital),
                          flush=True)

                    update_requests.append(
                        UpdateOne(
                            {'code': code, 'date': date},
                            {'$set': {'code': code, 'date': date, self.name: total_capital}}, upsert=True))

                except:
                    print('计算规模因子时发生异常,股票代码:%s,日期:%s'
                          % (code, date),
                          flush=True)

            if len(update_requests) > 0:
                save_result = self.collection.bulk_write(update_requests, ordered=False)
                print('股票代码: %s, 因子: %s, 插入:%4d, 更新: %4d' %
                      (code, self.name, save_result.upserted_count, save_result.modified_count), flush=True)
    def analyze(self):
        # 初始化对数据管理子系统接口的调用
        dm = DataModule()
        # 初始化对因子管理子系统接口的调用
        fm = FactorModule()

        # 获取分析周期内的
        all_dates = get_trading_dates(self.begin_date, self.end_date)

        # 首档和末档,股票代码和后复权价格的Dictionary
        top_dailies = dict()
        bottom_dailies = dict()
        # 暂存上一个调整
        last_adjust_date = None

        # 设置沪深300的首日值
        hs300_k = dm.get_k_data('000300',
                                index=True,
                                begin_date=all_dates[0],
                                end_date=all_dates[0])
        self.hs300_first_value = hs300_k.loc[0]['close']

        # 计算每日收益
        for index in range(0, len(all_dates), self.interval):
            adjust_date = all_dates[index]

            # 获取因子值,按照指定的顺序排序
            df_factor = fm.get_single_date_factors(self.factor, adjust_date)
            if df_factor.index.size == 0:
                continue
            df_factor.sort_values(self.factor,
                                  ascending=self.ascending,
                                  inplace=True)
            # 将股票代码设为index
            df_factor.set_index(['code'], inplace=True)

            # 获取当日所有股票的行情
            df_dailies = dm.get_one_day_k_data(autype='hfq', date=adjust_date)
            # 将code设为index
            df_dailies.set_index(['code'], inplace=True)

            # 计算收益
            self.compute_profit(last_adjust_date, df_dailies, top_dailies,
                                bottom_dailies, adjust_date)

            # 删除停牌股票
            df_dailies = df_dailies[df_dailies['is_trading']]
            # 计算每当包含的股票数
            total_size = df_dailies.index.size
            single_position_count = int(total_size / self.position)

            # 调整首档组合
            self.adjust_top_position(top_dailies, df_factor, df_dailies,
                                     single_position_count)

            # 调整末档组合
            self.adjust_bottom_position(bottom_dailies, df_factor, df_dailies,
                                        single_position_count)

            # 保存上一个调整日
            last_adjust_date = adjust_date

        # 生成零投资组合的组合收益
        self.profit_df[
            'portfolio'] = self.profit_df['top'] - self.profit_df['bottom']

        self.draw()