def fill_empty(result_list: list, store: MqQuarterStore, period_dict: dict, ts_code: str, update_date: str): period_list = list(period_dict.keys()) period_list.sort() for key in period_list: period_o: PeriodObj = period_dict[key] period = period_o.end_date for i in mq_quarter_metric_enum.fill_after_copy_fail_list: exist = store.find_period_latest(ts_code, i.name, period, update_date) if exist is None: call_add_nx = partial(add_nx, ts_code=ts_code, period=period, update_date=update_date, store=store, result_list=result_list, period_dict=period_dict, name=i.name) if i.from_name == '': call_add_nx(report_type=mq_report_type.report, value=Decimal(0)) else: from_indicator = store.find_period_exact( ts_code, i.from_name, period, update_date) if from_indicator is None or from_indicator.value is None: log.error( 'Cant find %s to fill %s for %s. Period: %s. Update date: %s' % (i.from_name, i.name, ts_code, period, update_date)) else: add = call_add_nx(report_type=0, value=from_indicator.value) add.report_type = from_indicator.report_type
def cal_yoy_mom(result_list: list, store: MqQuarterStore): for i in result_list: # type: MqQuarterMetric lm = store.find_period_latest(i.ts_code, i.name, date_utils.period_delta(i.period, -1)) i.mom = cal_inc_rate(i, lm) ly = store.find_period_latest(i.ts_code, i.name, date_utils.period_delta(i.period, -4)) i.yoy = cal_inc_rate(i, ly)
def cal_pepb(result_list: list, daily_store: mq_daily_store.MqDailyStore, quarter_store: mq_quarter_store.MqQuarterStore, ts_code: str, update_date: str): call_add = partial(common_add, result_list=result_list, store=daily_store) call_log = partial(common_log_err, ts_code=ts_code, update_date=update_date) total_mv = daily_store.find_date_exact(ts_code, mq_daily_metric_enum.total_mv.name, update_date) dprofit_ltm = quarter_store.find_latest(ts_code, mq_quarter_metric_enum.dprofit_ltm.name, update_date) dq_dividend(call_add, call_log, total_mv, dprofit_ltm, mq_daily_metric_enum.pe.name) nassets = quarter_store.find_latest(ts_code, mq_quarter_metric_enum.nassets.name, update_date) dq_dividend(call_add, call_log, total_mv, nassets, mq_daily_metric_enum.pb.name)
def cal_dcf(result_list: list, daily_store: mq_daily_store.MqDailyStore, quarter_store: mq_quarter_store.MqQuarterStore, dcf_service: MqDcfService, ts_code: str, update_date: str): ''' 根据自由现金流估算市值 ''' call_add = partial(common_add, result_list=result_list, store=daily_store) fcf = quarter_store.find_latest(ts_code, mq_quarter_metric_enum.fcf_ltm.name, update_date) mv_10, mv = 0, 0 report_type = mq_report_type.report period = '20000331' if fcf is not None: year = int(fcf.period[0:4]) report_type = fcf.report_type period = fcf.period mv_10, mv = dcf_service.cal_dcf(fcf.value, year, update_date) else: log.error('Cant find fcf %s %s' % (ts_code, update_date)) daily_mv_10 = MqDailyMetric(ts_code=ts_code, report_type=report_type, period=period, update_date=update_date, name=mq_daily_metric_enum.mv_10.name, value=mv_10) daily_mv = MqDailyMetric(ts_code=ts_code, report_type=report_type, period=period, update_date=update_date, name=mq_daily_metric_enum.mv.name, value=mv) call_add(to_add=daily_mv_10) call_add(to_add=daily_mv)
def extract_from_dividend(result_list: list, store: MqQuarterStore, period_dict: dict, d: TsDividend): # 有可能有非固定分红的派钱 lp: str = date_utils.latest_period_date(d.end_date) update_date: str = date_utils.format_delta(d.imp_ann_date, -1) call_add_nx = partial(add_nx, ts_code=d.ts_code, period=lp, update_date=update_date, report_type=mq_report_type.report, store=store, result_list=result_list, period_dict=period_dict) # 叠加到最近一个季度的分红中 dividend: Decimal = decimal_utils.mul(d.cash_div_tax, d.base_share) if lp != d.end_date: ori_d: MqQuarterMetric = store.find_period_latest( ts_code=d.ts_code, period=lp, update_date=update_date, name=mq_quarter_metric_enum.dividend.name) if ori_d is not None: dividend = dividend + ori_d.value call_add_nx(name='dividend', value=dividend)
def extract_from_cash_flow(result_list: list, store: MqQuarterStore, period_dict: dict, cf: TsCashFlow): update_date = date_utils.format_delta(cf.mq_ann_date, -1) ts_code = cf.ts_code period = cf.end_date call_find = partial(store.find_period_exact, ts_code=ts_code, period=period, update_date=update_date) call_add_nx = partial(add_nx, ts_code=ts_code, period=period, update_date=update_date, report_type=mq_report_type.report if cf.report_type == '1' else mq_report_type.report_adjust, store=store, result_list=result_list, period_dict=period_dict) for i in mq_quarter_metric_enum.extract_from_cf_list: if i.is_cf_h and date_utils.get_quarter_num(cf.end_date) == 3: q2: MqManualMetric = store.find_period_latest( ts_code=cf.ts_code, name=i.name, period=date_utils.period_delta(cf.end_date, -1), update_date=update_date) if q2 is None: log.error('Cant find q2 in cash flow %s %s %s' % (cf.ts_code, cf.end_date, cf.mq_ann_date)) call_add_nx(name=i.name, value=getattr(cf, i.from_name)) else: call_add_nx(name=i.name, value=q2.value) else: call_add_nx(name=i.name, value=getattr(cf, i.from_name))
def cal(daily_store: mq_daily_store.MqDailyStore, quarter_store: mq_quarter_store.MqQuarterStore, ts_code: str, update_date: str) -> MqDailyMetric: score = 0 peg = 0 report_type = 0 period = '00000000' pe: MqDailyMetric = daily_store.find_date_exact(ts_code, mq_daily_metric_enum.pe.name, update_date) dprofit_quarter = quarter_store.find_latest(ts_code, mq_quarter_metric_enum.dprofit_quarter.name, update_date) dprofit_quarter_ly = quarter_store.find_period_latest( ts_code, mq_quarter_metric_enum.dprofit_quarter.name, period=date_utils.period_delta(dprofit_quarter.period, -1), update_date=update_date) if dprofit_quarter is not None else None dprofit_ltm = quarter_store.find_latest(ts_code, mq_quarter_metric_enum.dprofit_ltm.name, update_date) if pe is None or dprofit_quarter is None or dprofit_quarter_ly is None or dprofit_ltm is None: score = -1 elif calculate.gt(pe, max_pe, field='value') or calculate.lt(pe, zero, field='value'): score = -1 elif calculate.lt(dprofit_quarter, zero, field='value') or calculate.lt(dprofit_quarter, min_yoy, field='yoy'): score = -1 elif calculate.lt(dprofit_quarter_ly, min_dprofit, field='value'): score = -1 elif calculate.lt(dprofit_ltm, zero, field='value') or \ calculate.lt(decimal_utils.div(dprofit_quarter.value, dprofit_ltm.value), min_dprofit_percent): score = -1 else: peg = decimal_utils.div(decimal_utils.div(pe.value, dprofit_quarter.yoy), 100) report_type = pe.report_type | dprofit_quarter.report_type period = max(pe.period, dprofit_quarter.period) if peg > max_peg: score = -1 else: score = (1 - peg / max_peg) * 100 peg_metric = MqDailyMetric(ts_code=ts_code, report_type=report_type, period=period, update_date=update_date, name=mq_daily_metric_enum.peg.name, value=peg) grow_score_metric = MqDailyMetric(ts_code=ts_code, report_type=report_type, period=period, update_date=update_date, name=mq_daily_metric_enum.grow_score.name, value=valid_score(score)) return [peg_metric, grow_score_metric]
def cal_dividend(result_list: list, daily_store: mq_daily_store.MqDailyStore, quarter_store: mq_quarter_store.MqQuarterStore, ts_code: str, update_date: str): call_add = partial(common_add, result_list=result_list, store=daily_store) call_log = partial(common_log_err, ts_code=ts_code, update_date=update_date) dividend_ltm = quarter_store.find_latest(ts_code, mq_quarter_metric_enum.dividend_ltm.name, update_date) total_mv = daily_store.find_date_exact(ts_code, mq_daily_metric_enum.total_mv.name, update_date) qd_dividend(call_add, call_log, dividend_ltm, total_mv, mq_daily_metric_enum.dividend_yields.name)
def earn_and_dividend_in_year(quarter_store: mq_quarter_store.MqQuarterStore, ts_code: str, report_period: str, update_date: str, year: int) -> bool: quarter_num = get_quarter_num(report_period) period = report_period if quarter_num == 4 else period_delta( report_period, -quarter_num) period = period_delta(period, 4) for i in range(year): period = period_delta(period, -4) dprofit_ltm = quarter_store.find_period_latest( ts_code, mq_quarter_metric_enum.dprofit_ltm.name, period, update_date) dividend_ltm = quarter_store.find_period_latest( ts_code, mq_quarter_metric_enum.dividend_ltm.name, period, update_date) if calculate.lt(dprofit_ltm, zero, 'value', True): return False if calculate.lt(dividend_ltm, zero, 'value', True): return False return True
def earn_in_period(quarter_store: mq_quarter_store.MqQuarterStore, ts_code: str, report_period: str, update_date: str, quarter_num: int) -> bool: period = period_delta(report_period, 1) for i in range(quarter_num): period = period_delta(period, -1) dprofit_quarter = quarter_store.find_period_latest( ts_code, mq_quarter_metric_enum.dprofit_quarter.name, period, update_date) if calculate.lt(dprofit_quarter, zero, 'value', True): return False return True
def extract_from_income_adjust(result_list: list, store: MqQuarterStore, period_dict: dict, income: TsIncome): update_date = date_utils.format_delta(income.mq_ann_date, -1) nprofit_new = store.find_period_exact(income.ts_code, mq_quarter_metric_enum.nprofit.name, income.end_date, update_date) nprofit_old = store.find_period_latest( income.ts_code, mq_quarter_metric_enum.nprofit.name, income.end_date, date_utils.format_delta(update_date, -1)) dprofit_old = store.find_period_latest( income.ts_code, mq_quarter_metric_enum.dprofit.name, income.end_date, date_utils.format_delta(update_date, -2)) to_add = None if nprofit_new is None: log.error('Cant find nprofit in adjust income. %s %s' % (income.ts_code, income.end_date)) elif nprofit_old is None or dprofit_old is None: to_add = MqQuarterMetric( ts_code=income.ts_code, report_type=(1 << mq_report_type.report_adjust), period=income.end_date, update_date=update_date, name=mq_quarter_metric_enum.dprofit.name, value=nprofit_new.value) else: to_add = MqQuarterMetric( ts_code=income.ts_code, report_type=(1 << mq_report_type.report_adjust), period=income.end_date, update_date=update_date, name=mq_quarter_metric_enum.dprofit.name, value=decimal_utils.sub( nprofit_new.value, decimal_utils.sub(nprofit_old.value, dprofit_old.value))) if to_add is not None: common_add(result_list, store, to_add)
def add_nx(ts_code: str, report_type: int, period: str, update_date: str, name: str, value: Decimal, result_list: list, store: MqQuarterStore, period_dict: dict): if value is None or name is None: return exist = store.find_period_latest(ts_code, name, period) if exist is not None and exist.update_date == update_date: return None to_add = MqQuarterMetric(ts_code=ts_code, report_type=(1 << report_type), period=period, update_date=update_date, name=name, value=value) common_add(result_list, store, to_add) period_dict[period] = PeriodObj(period, report_type) return to_add
def copy_indicator_from_latest(result_list: list, store: MqQuarterStore, period: PeriodObj, ts_code: str, update_date: str, name: str, from_name: str = None): if from_name is None: from_name = name i = store.find_period_latest(ts_code, from_name, period.end_date, update_date) if i is None or i.update_date == update_date: return ni = MqQuarterMetric(ts_code=i.ts_code, report_type=i.report_type, period=i.period, update_date=update_date, name=name, value=i.value) common_add(result_list, store, ni)
def extract_from_forecast(result_list: list, store: MqQuarterStore, period_dict: dict, forecast: TsForecast): update_date = date_utils.format_delta(forecast.ann_date, -1) call_add_nx = partial(add_nx, ts_code=forecast.ts_code, period=forecast.end_date, update_date=update_date, report_type=mq_report_type.forecast, store=store, result_list=result_list, period_dict=period_dict) forecast_nprofit = None if forecast.net_profit_min is not None: forecast_nprofit = forecast.net_profit_min elif forecast.net_profit_max is not None: forecast_nprofit = forecast.net_profit_max else: percent = None # choose minimum percent. if forecast.p_change_min is not None: percent = forecast.p_change_min if forecast.p_change_max is not None: if percent is None or forecast.p_change_max < percent: percent = forecast.p_change_max if percent is not None: percent = (percent / 100) + 1 if forecast.last_parent_net is not None: forecast_nprofit = percent * forecast.last_parent_net else: nprofit_ly = store.find_period_latest( forecast.ts_code, mq_quarter_metric_enum.nprofit.name, forecast.end_date, update_date) if nprofit_ly is not None and nprofit_ly.value is not None: forecast_nprofit = percent * nprofit_ly.value call_add_nx(name=mq_quarter_metric_enum.nprofit.name, value=forecast_nprofit)
def history_dividend_yoy_score(quarter_store: mq_quarter_store.MqQuarterStore, ts_code: str, report_period: str, update_date: str, year: int) -> bool: quarter_num = get_quarter_num(report_period) period = report_period if quarter_num == 4 else period_delta( report_period, -quarter_num) period = period_delta(period, 4) yoy_list = [] for i in range(year): period = period_delta(period, -4) dividend_ltm = quarter_store.find_period_latest( ts_code, mq_quarter_metric_enum.dividend_ltm.name, period, update_date) yoy_list.append(calculate.get_val(dividend_ltm, 'yoy', zero)) result = 0 score_per_one = 100 / year for yoy in yoy_list: if yoy > 0: result += score_per_one elif yoy < 0: result -= score_per_one / 2 return decimal_utils.valid_score(result)
def common_add(result_list: list, store: MqQuarterStore, to_add: MqQuarterMetric): store.add(to_add) result_list.append(to_add)