Beispiel #1
0
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)
Beispiel #2
0
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
Beispiel #3
0
def cal_quarter_ltm(result_list: list, store: MqQuarterStore,
                    period_o: PeriodObj, ts_code: str, update_date: str):
    period = period_o.end_date
    quarter_num = date_utils.get_quarter_num(period)
    report_type = period_o.report_type
    call_find_now = partial(store.find_period_exact,
                            ts_code=ts_code,
                            update_date=update_date)
    call_find_pre = partial(store.find_period_latest,
                            ts_code=ts_code,
                            update_date=update_date)
    call_add = partial(common_add, result_list=result_list, store=store)

    for k in mq_quarter_metric_enum.cal_quarter_list:
        name = k.name
        from_name = k.from_name
        i1 = call_find_now(period=period, name=from_name)
        i2 = call_find_pre(period=date_utils.period_delta(period, -1),
                           name=from_name)
        quarter = quarter_cal_utils.cal_quarter(name, i1, i2)
        if quarter is None:
            common_log_err(ts_code, period, report_type, update_date, name)
        else:
            call_add(to_add=quarter)

    for k in mq_quarter_metric_enum.cal_ltm_list:
        name = k.name
        from_name = k.from_name
        i1 = call_find_now(period=period, name=from_name)
        i2 = call_find_pre(period=date_utils.period_delta(period, -1),
                           name=from_name)
        i3 = call_find_pre(period=date_utils.period_delta(period, -2),
                           name=from_name)
        i4 = call_find_pre(period=date_utils.period_delta(period, -3),
                           name=from_name)

        ltm: MqQuarterMetric = quarter_cal_utils.cal_ltm_with_quarter(
            name, i1, i2, i3, i4)
        if ltm is None and quarter_num == 4:
            q_m: MqQuarterMetricEnum = mq_quarter_metric_enum.find_by_name(
                from_name)
            ltm = quarter_cal_utils.add_up(
                name, [call_find_now(period=period, name=q_m.from_name)])

        if ltm is None:
            common_log_err(ts_code, period, report_type, update_date, name)
        else:
            call_add(to_add=ltm)
Beispiel #4
0
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))
Beispiel #5
0
def fetch_from_period():
    s: Session = db_client.get_session()
    result = s.query(func.max(TsCashFlow.end_date)) \
        .all()
    s.close()
    from_date = fetch_data_start_period
    if len(result) > 0 and not result[0][0] is None:
        from_date = date_utils.period_delta(result[0][0], -4)
    return from_date
Beispiel #6
0
def fetch_by_period(to_date: str = date_utils.get_current_dt()):
    to_period = date_utils.period_delta(date_utils.next_period(to_date),
                                        1)  # 年报和一季度的预报可能同时出
    from_period = fetch_from_period()
    return fetch.common_fetch_report_by_period(TsForecast,
                                               'fetch_forecast',
                                               TsForecast.end_date,
                                               from_period=from_period,
                                               to_period=to_period)
Beispiel #7
0
def cal_complex_quarter_ltm(result_list: list, store: MqQuarterStore,
                            period_o: PeriodObj, ts_code: str,
                            update_date: str):
    '''
    计算复杂指标的单季和ltm, 在所有复杂指标计算后
    暂无
    '''
    period = period_o.end_date
    report_type = period_o.report_type
    call_find_now = partial(store.find_period_exact,
                            ts_code=ts_code,
                            update_date=update_date)
    call_find_pre = partial(store.find_period_latest,
                            ts_code=ts_code,
                            update_date=update_date)
    call_add = partial(common_add, result_list=result_list, store=store)

    for k in mq_quarter_metric_enum.complex_quarter_list:
        name = k.name
        from_name = k.from_name
        current = call_find_now(period=period, name=from_name)
        lp = call_find_pre(period=date_utils.period_delta(period, -1),
                           name=from_name)
        quarter = quarter_cal_utils.cal_quarter(name, current, lp)
        if quarter is None:
            common_log_err(ts_code, period, report_type, update_date, name)
        else:
            call_add(to_add=quarter)

    for k in mq_quarter_metric_enum.complex_ltm_list:
        name = k.name
        from_name = k.from_name
        current = call_find_now(period=period, name=from_name)
        last_year_q4 = call_find_pre(period=date_utils.q4_last_year(period),
                                     name=from_name)
        last_year = call_find_pre(period=date_utils.period_delta(period, -4),
                                  name=from_name)
        ltm = quarter_cal_utils.cal_ltm_with_period(name, current,
                                                    last_year_q4, last_year)
        if ltm is None:
            common_log_err(ts_code, period, report_type, update_date, name)
        else:
            call_add(to_add=ltm)
Beispiel #8
0
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
Beispiel #9
0
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)
Beispiel #10
0
def cal_avg(result_list: list, store: MqQuarterStore, period_o: PeriodObj,
            ts_code: str, update_date: str):
    period = period_o.end_date
    report_type = period_o.report_type
    call_find_now = partial(store.find_period_exact,
                            ts_code=ts_code,
                            update_date=update_date)
    call_find_pre = partial(store.find_period_latest, ts_code=ts_code)
    call_add = partial(common_add, result_list=result_list, store=store)
    for k in mq_quarter_metric_enum.cal_avg_list:
        from_name = k.from_name
        i1 = call_find_now(period=period, name=from_name)
        i2 = call_find_pre(period=date_utils.period_delta(period, -1),
                           name=from_name)
        i3 = call_find_pre(period=date_utils.period_delta(period, -2),
                           name=from_name)
        i4 = call_find_pre(period=date_utils.period_delta(period, -3),
                           name=from_name)
        avg = quarter_cal_utils.cal_ltm_avg(k.name, i1, i2, i3, i4)
        if avg is None:
            common_log_err(ts_code, period, report_type, update_date, k.name)
        else:
            call_add(to_add=avg)
Beispiel #11
0
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]
Beispiel #12
0
def generate_report_message_by_code(
    ts_code: str, share_name: str, to_date: str = date_utils.get_current_dt()):
    result_list = []
    from_date = mq_calculate_start_date
    session = db_client.get_session()
    last_one: MqMessage = session.query(MqMessage) \
        .filter(MqMessage.ts_code == ts_code, MqMessage.msg_type <= 3) \
        .order_by(MqMessage.pub_date.desc()).limit(1).all()
    if len(last_one) > 0:
        from_date = date_utils.format_delta(last_one[0].pub_date, 1)

    quarter_store = mq_quarter_store.init_quarter_store_by_date(
        ts_code, from_date)
    session.close()

    while from_date <= to_date:  # type: MqQuarterBasic
        latest = quarter_store.find_latest(ts_code,
                                           mq_quarter_metric_enum.dprofit.name,
                                           from_date)
        if latest is None:
            from_date = date_utils.format_delta(from_date, 1)
            continue
        for i in range(5):
            period = date_utils.period_delta(latest.period, -i)
            dprofit = quarter_store.find_period_exact(
                ts_code, mq_quarter_metric_enum.dprofit.name, period,
                from_date)
            if dprofit is None:
                continue
            # 只保留官方财报
            if not ((dprofit.report_type & (1 << mq_report_type.report)) > 0 or \
                    (dprofit.report_type & (1 << mq_report_type.forecast)) > 0 or \
                    (dprofit.report_type & (1 << mq_report_type.express)) > 0):
                continue
            result_list.append(
                MqMessage(ts_code=ts_code,
                          msg_type=mq_message_type.report,
                          message=get_report_message_content(
                              dprofit, share_name),
                          pub_date=date_utils.format_delta(from_date, 1)))
        from_date = date_utils.format_delta(from_date, 1)

    return result_list
Beispiel #13
0
def cal_fcf(result_list: list, store: MqQuarterStore, period_o: PeriodObj,
            ts_code: str, update_date: str):
    '''
    计算自由现金流,依赖于 cal_rev_pay, cal_quarter_ltm
    '''
    period = period_o.end_date
    report_type = period_o.report_type
    call_find = partial(store.find_period_exact,
                        ts_code=ts_code,
                        period=period,
                        update_date=update_date)
    call_find_ly = partial(store.find_period_latest,
                           ts_code=ts_code,
                           period=date_utils.q4_last_year(period))
    call_find_lp = partial(store.find_period_latest,
                           ts_code=ts_code,
                           period=date_utils.period_delta(period, -1))
    call_add = partial(common_add, result_list=result_list, store=store)
    call_log = partial(common_log_err,
                       ts_code=ts_code,
                       period=period,
                       update_date=update_date,
                       report_type=report_type)

    if mq_report_type.is_report(report_type):
        total_receivable_delta = common_cal_delta(call_find, call_find_ly,
                                                  'total_receivable')
        prepayment_delta = common_cal_delta(call_find, call_find_ly,
                                            'prepayment')
        # 经营性应收项目增加 = 应收账款增加 + 预付账款增加 + 应收票据增加
        op_recv_delta = quarter_cal_utils.add_up(
            'op_recv_delta', [total_receivable_delta, prepayment_delta])

        total_payable_delta = common_cal_delta(call_find, call_find_ly,
                                               'total_payable')
        adv_receipts_delta = common_cal_delta(call_find, call_find_ly,
                                              'adv_receipts')
        # 经营性应付项目增加 = 应付账款增加 + 预收账款增加 + 应付票据增加
        op_pay_delta = quarter_cal_utils.add_up(
            'op_pay_delta', [total_payable_delta, adv_receipts_delta])

        inventories_delta = common_cal_delta(call_find, call_find_ly,
                                             'inventories')
        lt_amor_exp_delta = common_cal_delta(call_find, call_find_ly,
                                             'lt_amor_exp')

        # 营运资本增加 = 存货增加 + 经营性应收项目增加 + 长期待摊费用增加 - 经营性应付项目增加 - 预提费用增加 (已经取消)
        op_cap_delta = quarter_cal_utils.sub_from('op_cap_delta', [
            quarter_cal_utils.add_up(
                '_', [inventories_delta, op_recv_delta, lt_amor_exp_delta]),
            op_pay_delta
        ])

        prov_depr_assets = call_find(name='prov_depr_assets')
        depr_fa_coga_dpba = call_find(name='depr_fa_coga_dpba')
        amort_intang_assets = call_find(name='amort_intang_assets')
        lt_amort_deferred_exp = call_find(name='lt_amort_deferred_exp')
        loss_scr_fa = call_find(name='loss_scr_fa')
        # 折旧与摊销 = 资产减值准备 + 固定资产折旧 + 无形资产摊销 + 长期待摊费用摊销 + 固定资产报废损失
        daa = quarter_cal_utils.add_up('daa', [
            prov_depr_assets, depr_fa_coga_dpba, amort_intang_assets,
            lt_amort_deferred_exp, loss_scr_fa
        ])

        # 资本支出 = 非流动性资产增加 - 可供出售金融资产增加
        total_nca_delta = common_cal_delta(call_find, call_find_ly,
                                           'total_nca')
        fa_avail_for_sale_delta = common_cal_delta(call_find, call_find_ly,
                                                   'fa_avail_for_sale')
        fa_avail_for_sale_delta = None  # 取消了
        cap_cost = quarter_cal_utils.sub_from(
            'cap_cost', [total_nca_delta, fa_avail_for_sale_delta])

        dprofit = call_find(name='dprofit')
        # 自由现金流 = 归母扣非净利 + 折旧与摊销 - 营运资本增加 - 资本支出
        fcf = quarter_cal_utils.sub_from('fcf', [
            quarter_cal_utils.add_up('_', [dprofit, daa]), op_cap_delta,
            cap_cost
        ])

    else:
        dprofit_ltm_lp = call_find_lp(name='dprofit_ltm')
        fcf_ltm_lp = call_find_lp(name='fcf_ltm')
        dprofit = call_find(name='dprofit')
        fcf = quarter_cal_utils.multiply(
            dprofit, quarter_cal_utils.dividend(fcf_ltm_lp, dprofit_ltm_lp,
                                                '_'), 'fcf')

    if fcf is None or fcf.period != period:
        call_log(name='fcf')
    else:
        call_add(to_add=fcf)