def cashflow_free_y(): '''投资:自由现金流''' return MetricsMeta('f_cashflow_free_y', expr.Sub(expr.Get('n_cashflow_act', period='y'), expr.Get('c_pay_acq_const_fiolta', period='y')), display='自由现金流')
def days_prepayment_y(): '''预付账款周转天数''' return MetricsMeta('f_days_prepayment_y', expr.Div( expr.Multi(expr.Get('f_prepayment_ave_y'), expr.Value(360)), expr.Get('oper_cost', period='y')), display='预付账款周转天数')
def days_adv_receipts_y(): '''预收账款周转天数''' return MetricsMeta('f_days_adv_receipts_y', expr.Div( expr.Multi(expr.Get('f_adv_receipts_ave_y'), expr.Value(360)), expr.Get('revenue', period='y')), display='预收账款周转天数')
def interest_bearing_liab_ratio_y(): ''' 有息负债率 = 有息负债 / 总资产 同行比较,越高风险越大 ''' return MetricsMeta('f_interest_bearing_liab_y.r', expr.Div(expr.Get('f_interest_bearing_liab_y'), expr.Get('f_total_assets_y')), display='有息负债率')
def gross_profit_ratio(): '''毛利率%''' return MetricsMeta('f_gross_profit.r', expr.Sub( expr.Value(1), expr.Div(expr.Get('oper_cost'), expr.Get('revenue'))), display='毛利率')
def exp_3_ratio(): '''三费占比''' return MetricsMeta('f_exp_3.r', expr.Div( expr.Sum(expr.Get('sell_exp'), expr.Get('admin_exp'), expr.Get('fin_exp')), expr.Get('revenue')), display='三费占比')
def days_inventory_y(): '''存货周转天数''' return MetricsMeta('f_days_inventory_y', expr.Div( expr.Multi(expr.Get('f_inventory_ave_y'), expr.Value(360)), expr.Get('oper_cost', period='y')), display='存货周转天数')
def test_market_cap(self): m = goose.market_cap(7, 2) v = m.eval(self.stock, 2019, 1) s1 = expr.Get('total_hldr_eqy_exc_min_int').eval(self.stock, 2019, 1) s2 = expr.Get('f_roe_ttm').eval(self.stock, 2019, 1) s3 = goose.growth_factor().eval(self.stock, 2019, 1) self.assertEqual(s1*math.pow((1+s2), (7+2+s3)), v)
def inventroy_ave_y(): '''平均存货''' return MetricsMeta( 'f_inventory_ave_y', expr.Div( expr.Sum( expr.Get('inventories', period='y'), expr.Before(expr.Get('inventories', period='y'), past_year=1)), expr.Value(2)))
def interest_bearing_liab(): ''' 有息负债 = 短期借款 + 1年内到期的长期负债 + 长期借款 + 应付债券 + 长期应付款 ''' return MetricsMeta( 'f_interest_bearing_liab', expr.Sum(expr.Get('lt_borr'), expr.Get('st_borr'), expr.Get('bond_payable'), expr.Get('lt_payable'), expr.Get('non_cur_liab_due_1y')))
def leverage(): ''' 杠杆倍数 = 资产/所有者权益 = 资产/(资产-负债) = 1/(1-资产负债率) ''' return MetricsMeta('f_leverage', expr.Div(expr.Get('f_total_assets'), expr.Get('total_hldr_eqy_exc_min_int')), display='杠杆倍数')
def assets_liab_ratio_y(): ''' 资产负债率 >50%需小心 同行比较,越高风险越大 ''' return MetricsMeta( 'f_assets_liab_y.r', expr.Div(expr.Get('total_liab', period='y'), expr.Get('f_total_assets_y')))
def run(y, q): v = m.expr.eval(self.stock, y, 4) s1 = expr.Get('n_income_attr_p').eval(self.stock, y, q) s2 = expr.Get('total_hldr_eqy_exc_min_int').eval(self.stock, y, q) s3 = expr.Get('total_hldr_eqy_exc_min_int').eval( self.stock, y - 1, q) a = s1 / ((s2 + s3) / 2) print(y, q, a, v) self.assertEqual(a, v, '{} {}'.format(y, q))
def days_acct_payable_y(): '''应付账款周转天数''' return MetricsMeta('f_days_acct_payable_y', expr.Div( expr.Multi(expr.Get('f_acct_payable_ave_y'), expr.Value(360)), expr.Sub(expr.Get('oper_cost', period='y'), expr.Get('inventories', period='y'))), display='应付账款周转天数')
def adv_receipts_ave_y(): '''平均预收账款''' return MetricsMeta( 'f_adv_receipts_ave_y', expr.Div( expr.Sum( expr.Get('adv_receipts', period='y'), expr.Before(expr.Get('adv_receipts', period='y'), past_year=1)), expr.Value(2)))
def prepayment_ave_y(): '''平均预付账款''' return MetricsMeta( 'f_prepayment_ave_y', expr.Div( expr.Sum( expr.Get('prepayment', period='y'), expr.Before(expr.Get('prepayment', period='y'), past_year=1)), expr.Value(2)))
def market_cap(base: int, moat: int): ''' 估算总市值 = 净资产 * (1+滚动roe) ^ (基本因子+护城河因子+成长因子) ''' return expr.Multi(expr.Get('total_hldr_eqy_exc_min_int'), expr.Power(expr.Sum(expr.Value(1), expr.Get('f_roe_ttm')), expr.Sum(base_factor(base), moat_factor(moat), growth_factor())))
def net_operating_cycle(): '''营销:净营业周期''' return MetricsMeta('f_net_op_cycle_y', expr.Sub( expr.Sum(expr.Get('f_days_inventory_y'), expr.Get('f_days_accounts_receiv_y'), expr.Get('f_days_prepayment_y')), expr.Get('f_days_acct_payable_y'), expr.Get('f_days_adv_receipts_y')), display='净营业周期')
def acct_payable_ave_y(): '''平均应付账款''' return MetricsMeta( 'f_acct_payable_ave_y', expr.Div( expr.Sum( expr.Get('acct_payable', period='y'), expr.Get('notes_payable', period='y'), expr.Before(expr.Get('acct_payable', period='y'), past_year=1), expr.Before(expr.Get('notes_payable', period='y'), past_year=1)), expr.Value(2)))
def accounts_receiv_ave_y(): '''平均应收账款''' return MetricsMeta( 'f_accounts_receiv_ave_y', expr.Div( expr.Sum( expr.Get('accounts_receiv', period='y'), expr.Before(expr.Get('accounts_receiv', period='y'), past_year=1), expr.Get('notes_receiv', period='y'), expr.Before(expr.Get('notes_receiv', period='y'), past_year=1)), expr.Value(2)))
def income_attr_p_ttm(): # 滚动净利润:最近连续4个季度 ttm_q3 = [expr.Before(expr.Get('n_income_attr_p', increment=True, var_type='f'), past_quarter=i) for i in range(1, 4)] return MetricsMeta('f_income_attr_p_ttm', expr.Sum(expr.Get('n_income_attr_p', increment=True, var_type='f'), ttm_q3))
def test_roe_ttm(self): m = roe.roe_ttm() # n_income_arrt_p(2019.1) / ((total_hldr_eqy_exc_min_int(2018.4) # +total_hldr_eqy_exc_min_int(2019.1)) # /2) v = m.expr.eval(self.stock, 2019, 1) s1 = expr.Get('f_income_attr_p_ttm').eval(self.stock, 2019, 1) s2 = expr.Get('total_hldr_eqy_exc_min_int').eval(self.stock, 2019, 1) s3 = expr.Get('total_hldr_eqy_exc_min_int').eval(self.stock, 2018, 1) self.assertEqual(s1 / (s2 + s3) * 2, v)
def net_profit_growth_pay_10_years_ratio(): '''10年净利润增长/10年资本开支比''' return MetricsMeta( 'f_n_income_attr_p_pay_10_y.r', expr.Div( expr.Sub( expr.Get('n_income_attr_p', period='y'), expr.Before(expr.Get('n_income_attr_p', period='y'), past_year=9)), expr.Sum(expr.Get('c_pay_acq_const_fiolta', period='y'), [ expr.Before(expr.Get('c_pay_acq_const_fiolta', period='y'), past_year=n) for n in range(1, 10) ])), display='10年净利润增长与资本开支比')
def cashflow_free_pay_10_years_ratio(): '''10年自由现金流/10年资本开支比''' return MetricsMeta( 'f_cashflow_free_pay_10_y.r', expr.Div( expr.Sum(expr.Get('f_cashflow_free_y'), [ expr.Before(expr.Get('f_cashflow_free_y'), past_year=n) for n in range(1, 10) ]), expr.Sum(expr.Get('c_pay_acq_const_fiolta', period='y'), [ expr.Before(expr.Get('c_pay_acq_const_fiolta', period='y'), past_year=n) for n in range(1, 10) ])), display='10年自由现金流与资本开支比')
def roe(): ''' 年度ROE(平均) =净利润/净资产 =归母净利润/(期初+期末归母净资产)/2 =每股净利润/每股净资产 =销售净利率*总资产周转率*杠杆系数 ''' return MetricsMeta( 'f_roe', expr.Div( expr.Get('n_income_attr_p'), expr.Div( expr.Sum( expr.Get('total_hldr_eqy_exc_min_int'), expr.Get('total_hldr_eqy_exc_min_int', period_begin=True)), expr.Value(2))))
def run(y, q): rm = expr.Range(expr.Before(expr.Get('f_roe_y'), past_year=1), year_count=6) nm = self.roe_ge_15_pct_now() v = rm.eval(self.stock, y, 4) v2 = expr.Ge(rm, expr.Value(0.15)).eval(self.stock, y, 4) print('last 6 years', v, v2) v3 = nm.eval(self.stock, y, q) print('current', v3, expr.Get('f_roe').eval(self.stock, y, q)) v4 = expr.And(expr.Ge(rm, expr.Value(0.15)), nm).eval(self.stock, y, q) print('last 7 years', v4)
def test_price_share(self): mc = goose.market_cap(7, 2) ps = goose.price_share(mc) v = ps.eval(self.stock, 2019, 1) s1 = mc.eval(self.stock, 2019, 1) s2 = expr.Get('total_share').eval(self.stock, 2019, 1) self.assertEqual(s1/s2, v)
def roe_ge_15_pct_now(self): def fv(stock: expr.ExprCtx, year: int, quarter: int): v = { 4: 0.15, 3: 0.15 / 4 * 3, 2: 0.15 / 4 * 2, 1: 0.15 / 4, } return v[quarter] return expr.Ge(expr.Get('f_roe'), expr.FuncValue(fv))
def show(self, ts_code: str, year: int, quarter: int, metrics: []): db = StockDb(**self.__cfg) stocks = db.list() filter = expr.Eq(expr.Get('i_ts_code'), expr.Value(ts_code)) selected = stocks.query_by_basic_info(filter) stock = selected[0] Report = self.__get_metrics_report() report = Report(stock) report.set_metrics(metrics) report.eval(year, quarter) report.show(f'{stock["ts_code"]}({stock["name"]})')
def eval(self, ts_code: str, year: int, quarter: int, path: str, report='w'): '''Evalute the value of a stock. Args: ts_code: stock code year: report year quarter: report quarter path: the path to be report: report type. w=white horse.default is w. ''' db = StockDb(**self.__cfg) stocks = db.list() filter = expr.Eq(expr.Get('i_ts_code'), expr.Value(ts_code)) if ts_code is None: filter = expr.Eq(expr.Value(1), expr.Value(1)) selected = stocks.query_by_basic_info(filter) Report = self.__get_report(report) def do_report(stock, y, q): try: print(stock['ts_code'], stock['name'], 'to_excel') report = Report(stock) report.eval(year, quarter) report.to_excel( f'{path}/{stock["ts_code"]}_{stock["name"]}_{year}_{quarter}.xlsx') return report except Exception as e: print(stock['ts_code'], stock['name'], e) fs = [] for stock in selected: with concurrent.futures.ThreadPoolExecutor() as executor: fs.append( { 'r': executor.submit(do_report, stock, year, quarter), 'ts_code': stock['ts_code'], 'name': stock['name'], }) for stock in fs: try: report = stock['r'].result() if report is None: continue print(stock['ts_code'], stock['name'], 'to_chart') report.to_chart( f'{path}/{stock["ts_code"]}_{stock["name"]}_{year}_{quarter}.pdf', f'{stock["ts_code"]} {stock["name"]} {year}年{quarter}季' ) except Exception as e: print(e)