def _calc_factor_loading(cls, code, calc_date): """ 计算指定日期、指定个股ETOP因子载荷 Parameters: -------- :param code: str 个股代码, 如SH600000, 600000 :param calc_date: datetime-like, str 计算日期, 格式: YYYY-MM-DD :return: pd.Series -------- 个股的ETOP因子载荷 0. code 1. etop 如果计算失败, 返回None """ code = Utils.code_to_symbol(code) # 读取个股的ttm净利润 ttm_fin_data = Utils.get_ttm_fin_basic_data(code, calc_date) if ttm_fin_data is None: return None ttm_netprofit = ttm_fin_data['NetProfit'] if pd.isnull(ttm_netprofit): return None # 读取个股市值 lncap_path = os.path.join(factor_ct.FACTOR_DB.db_path, risk_ct.LNCAP_CT.db_file) lncap_data = Utils.read_factor_loading(lncap_path, Utils.datetimelike_to_str(calc_date, dash=False), code) if lncap_data.empty: return None secu_cap = np.exp(lncap_data['factorvalue']) # etop = ttm净利润/市值 etop = ttm_netprofit * 10000 / secu_cap return pd.Series([code, etop], index=['code', 'etop'])
def _calc_factor_loading(cls, code, calc_date): """ 计算指定日期、指定个股的成长因子,包含npg_ttm, opg_ttm Parameters: -------- :param code: str 个股代码,如600000或SH600000 :param calc_date: datetime-like or str 计算日期,格式YYYY-MM-DD, YYYYMMDD :return: pd.Series -------- 成长类因子值 0. id: 证券代码 1. npg_ttm: 净利润增长率_TTM 2. opg_ttm: 营业收入增长率_TTM 若计算失败, 返回None """ code = Utils.code_to_symbol(code) calc_date = Utils.to_date(calc_date) # 读取最新的TTM财务数据 ttm_fin_data_latest = Utils.get_ttm_fin_basic_data(code, calc_date) if ttm_fin_data_latest is None: return None # 读取去年同期TTM财务数据 try: pre_date = datetime.datetime(calc_date.year-1, calc_date.month, calc_date.day) except ValueError: pre_date = calc_date - datetime.timedelta(days=366) ttm_fin_data_pre = Utils.get_ttm_fin_basic_data(code, pre_date) if ttm_fin_data_pre is None: return None # 计算成长类因子值 if abs(ttm_fin_data_pre['NetProfit']) < 0.1: return None npg_ttm = (ttm_fin_data_latest['NetProfit'] - ttm_fin_data_pre['NetProfit']) / abs(ttm_fin_data_pre['NetProfit']) if abs(ttm_fin_data_pre['MainOperateRevenue']) < 0.1: return None opg_ttm = (ttm_fin_data_latest['MainOperateRevenue'] - ttm_fin_data_pre['MainOperateRevenue']) / abs(ttm_fin_data_pre['MainOperateRevenue']) return Series([code, round(npg_ttm, 4), round(opg_ttm, 4)], index=['id', 'npg_ttm', 'opg_ttm'])
def _calc_factor_loading(cls, code, calc_date): """ 计算指定日期、指定个股的价值因子,包含ep_ttm, bp_lr, ocf_ttm Parameters: -------- :param code: str 个股代码:如600000或SH600000 :param calc_date: datetime-like or str 计算日期,格式YYYY-MM-DD, YYYYMMDD :return: pd.Series -------- 价值类因子值 0. ep_ttm: TTM净利润/总市值 1. bp_lr: 净资产(最新财报)/总市值 2. ocf_ttm: TTM经营性现金流/总市值 若计算失败,返回None """ code = Utils.code_to_symbol(code) calc_date = Utils.to_date(calc_date) # 读取TTM财务数据 ttm_fin_data = Utils.get_ttm_fin_basic_data(code, calc_date) if ttm_fin_data is None: return None # 读取最新财报数据 report_date = Utils.get_fin_report_date(calc_date) fin_basic_data = Utils.get_fin_basic_data(code, report_date) if fin_basic_data is None: return None # 计算总市值 mkt_daily = Utils.get_secu_daily_mkt(code, calc_date, fq=False, range_lookup=True) if mkt_daily.shape[0] == 0: return None cap_struct = Utils.get_cap_struct(code, calc_date) if cap_struct is None: return None total_cap = cap_struct.total - cap_struct.liquid_b - cap_struct.liquid_h total_mkt_cap = total_cap * mkt_daily.close # 计算价值类因子 ep_ttm = ttm_fin_data[ 'NetProfit'] * util_ct.FIN_DATA_AMOUNT_UNIT / total_mkt_cap ocf_ttm = ttm_fin_data[ 'NetOperateCashFlow'] * util_ct.FIN_DATA_AMOUNT_UNIT / total_mkt_cap bp_lr = fin_basic_data[ 'ShareHolderEquity'] * util_ct.FIN_DATA_AMOUNT_UNIT / total_mkt_cap return Series([round(ep_ttm, 6), round(bp_lr, 6), round(ocf_ttm, 6)], index=['ep_ttm', 'bp_lr', 'ocf_ttm'])
def _calc_factor_loading(cls, code, calc_date): """ 计算指定日期、指定个股EPFWD因子载荷 Parameters: -------- :param code: str 个股代码, 如SH600000, 600000 :param calc_date: datetime-like, str 计算日期, 格式: YYYY-MM-DD :return: pd.Series -------- 个股的EPFWD因子载荷 0. code 1. epfwd 如果计算失败, 返回None """ code = Utils.code_to_symbol(code) # 读取个股的预期盈利数据 predictedearnings_data = Utils.get_consensus_data( calc_date, code, ConsensusType.PredictedEarings) if predictedearnings_data is None: # 如果个股的预期盈利数据不存在, 那么代替ttm净利润 ttm_fin_data = Utils.get_ttm_fin_basic_data(code, calc_date) if ttm_fin_data is None: return None predictedearnings_data = pd.Series( [code, ttm_fin_data['NetProfit']], index=['code', 'predicted_earnings']) fpredictedearnings = predictedearnings_data['predicted_earnings'] if np.isnan(fpredictedearnings): return None # 读取个股市值 size_path = os.path.join(factor_ct.FACTOR_DB.db_path, risk_ct.LNCAP_CT.db_file) size_factor_loading = Utils.read_factor_loading( size_path, Utils.datetimelike_to_str(calc_date, dash=False), code) if size_factor_loading.empty: return None # epfwd = 盈利预期/市值 epfwd = fpredictedearnings * 10000.0 / np.exp( size_factor_loading['factorvalue']) return pd.Series([code, epfwd], index=['code', 'epfwd'])
def _calc_factor_loading(cls, code, calc_date): """ 计算指定日期、指定个股CETOP因子载荷 Parameters: -------- :param code: str 个股代码, 如SH600000, 600000 :param calc_date: datetime-like, str 计算日期, 格式: YYYY-MM-DD :return: pd.Series -------- 个股的CETOP因子载荷 0. code 1. cetop 如果计算失败, 返回None """ code = Utils.code_to_symbol(code) # 读取个股的主要财务指标数据ttm值 ttm_fin_data = Utils.get_ttm_fin_basic_data(code, calc_date) if ttm_fin_data is None: return None ttm_cash = ttm_fin_data['NetOperateCashFlow'] if np.isnan(ttm_cash): return None # 读取个股市值 lncap_path = os.path.join(factor_ct.FACTOR_DB.db_path, risk_ct.LNCAP_CT.db_file) lncap_data = Utils.read_factor_loading( lncap_path, Utils.datetimelike_to_str(calc_date, dash=False), code) if lncap_data.empty: return None secu_cap = np.exp(lncap_data['factorvalue']) # cetop = 经营活动现金流ttm值/市值 cetop = ttm_cash * 10000 / secu_cap return pd.Series([code, cetop], index=['code', 'cetop'])
def _get_prevN_years_finbasicdata(date, code, years): """ 读取过去n年的主要财务指标数据, 其中每股数据会经过复权因子调整 :param date: datetime-like 日期 :param code: str 个股代码, 格式: SH600000 :param years: int 返回的报告期年数 :return: list of pd.Series """ year = date.year month = date.month if month in (1, 2, 3, 4): # report_dates = [datetime.datetime(year-5, 12, 31), # datetime.datetime(year-4, 12, 31), # datetime.datetime(year-3, 12, 31), # datetime.datetime(year-2, 12, 31)] report_dates = [ datetime.datetime(year - n, 12, 31) for n in range(years, 1, -1) ] is_ttm = True elif month in (5, 6, 7, 8): # report_dates = [datetime.datetime(year-5, 12, 31), # datetime.datetime(year-4, 12, 31), # datetime.datetime(year-3, 12, 31), # datetime.datetime(year-2, 12, 31), # datetime.datetime(year-1, 12, 31)] report_dates = [ datetime.datetime(year - n, 12, 31) for n in range(years, 0, -1) ] is_ttm = False else: # report_dates = [datetime.datetime(year-4, 12, 31), # datetime.datetime(year-3, 12, 31), # datetime.datetime(year-2, 12, 31), # datetime.datetime(year-1, 12, 31)] report_dates = [ datetime.datetime(year - n, 12, 31) for n in range(years - 1, 0, -1) ] is_ttm = True df_mkt_data = Utils.get_secu_daily_mkt(code, end=date, fq=True) # 个股复权行情, 用于调整每股数据 prevN_years_finbasicdata = [] for report_date in report_dates: fin_basic_data = Utils.get_fin_basic_data(code, report_date, date_type='report_date') if fin_basic_data is None: return None fin_basic_data = fin_basic_data.to_dict() df_extract_mkt = df_mkt_data[ df_mkt_data.date <= report_date.strftime('%Y-%m-%d')] if not df_extract_mkt.empty: fq_factor = df_extract_mkt.iloc[-1]['factor'] # 调整每股数据 fin_basic_data[ 'BasicEPS_adj'] = fin_basic_data['BasicEPS'] * fq_factor fin_basic_data['UnitNetAsset_adj'] = fin_basic_data[ 'UnitNetAsset'] * fq_factor fin_basic_data['UnitNetOperateCashFlow_adj'] = fin_basic_data[ 'UnitNetOperateCashFlow'] * fq_factor # 计算调整后的主营业务收入 fin_basic_data['MainOperateRevenue_adj'] = fin_basic_data[ 'MainOperateRevenue'] / fq_factor else: fin_basic_data['BasicEPS_adj'] = fin_basic_data['BasicEPS'] fin_basic_data['UnitNetAsset_adj'] = fin_basic_data['UnitNetAsset'] fin_basic_data['UnitNetOperateCashFlow_adj'] = fin_basic_data[ 'UnitNetOperateCashFlow'] fin_basic_data['MainOperateRevenue_adj'] = fin_basic_data[ 'MainOperateRevenue'] prevN_years_finbasicdata.append(fin_basic_data) if is_ttm: ttm_fin_basic_data = Utils.get_ttm_fin_basic_data(code, date) if ttm_fin_basic_data is None: return None ttm_fin_basic_data = ttm_fin_basic_data.to_dict() df_extract_mkt = df_mkt_data[ df_mkt_data.date <= ttm_fin_basic_data['ReportDate'].strftime( '%Y-%m-%d')] if not df_extract_mkt.empty: fq_factor = df_extract_mkt.iloc[-1]['factor'] # 调整每股数据 ttm_fin_basic_data[ 'BasicEPS_adj'] = ttm_fin_basic_data['BasicEPS'] * fq_factor # 计算调整后的主营业务收入 ttm_fin_basic_data['MainOperateRevenue_adj'] = ttm_fin_basic_data[ 'MainOperateRevenue'] / fq_factor else: ttm_fin_basic_data['BasicEPS_adj'] = ttm_fin_basic_data['BasicEPS'] ttm_fin_basic_data['MainOperateRevenue_adj'] = ttm_fin_basic_data[ 'MainOperateRevenue'] prevN_years_finbasicdata.append(ttm_fin_basic_data) return prevN_years_finbasicdata