背景
上次做的这个程序:
Python自动获取指定上市公司的所有财务数据(资产负债表,利润表,现金流量表)
很受欢迎,我知道很多经管类的同学需要获取财务数据,但是我没想到他们居然这么高频的需求,并且这么低的动手能力...........而且,但是吧,上次的tushare库的api_key过期了,不能用了。
并且上次做的程序也很简陋,也不符合用户的体验。
我这次全新升级,用户不需要再弄一堆乱七八糟的txt文件,只需要双击一个exe就能有完好的UI界面,输入自己想要的股票的名称,就能够查询到所有的上市公司数据,并且还能够计算一些常见的财务指标。
代码还是开源!但我知道很多同学看了代码也不会写,写了也不会配环境去用,就算都会,自己账号也没权限获取数据。(要获取财务数据需要充两百块钱)
我不可能公开我个人账号的api_key给大家用,但是我可以嵌入到 我用的exe应用里面去给大家用。
下载链接:财务数据获取接口
使用很简单,双击打开,输入要下载的股票代码
点击下载就好了。
就会存在本地excel文件,打开就是这样的:
想要多长时间就有多长时间,想要季度就有季度,想要年度就有年度。
还可以计算财务指标:
使用起来非常简洁和方便。
如果会Python,想自己动手的同学,想学是怎么做这个程序的,下面这次教大家怎么构建这样一个程序,从写代码,到构建为exe程序都有。但是重点在exe上面,因为上一篇文章已经很详细的写了这个获取财务数据的代码思路,所以说本次直接给代码就行了,不详细讲每一行代码是啥意思了。想学习tushare获取还是看这篇文章:
Python自动获取指定上市公司的所有财务数据(资产负债表,利润表,现金流量表)
代码实现
都是做数据科学的,做成应用web前端一个UI界面当然不擅长,所以这里就用streamlit包,来提供一个浏览器界面,方便用户使用。
streamlit代码如下,包含了获取财务数据的全流程:
# 定义一个空字典来存储变量名称和描述
variables_dict = {
"ts_code": "TS股票代码",
"ann_date": "公告日期",
"f_ann_date": "实际公告日期",
"end_date": "报告期",
"report_type": "报告类型 见底部表",
"comp_type": "公司类型(1一般工商业2银行3保险4证券)",
"end_type": "报告期类型",
"basic_eps": "基本每股收益",
"diluted_eps": "稀释每股收益",
"total_revenue": "营业总收入",
"revenue": "营业收入",
"int_income": "利息收入",
"prem_earned": "已赚保费",
"comm_income": "手续费及佣金收入",
"n_commis_income": "手续费及佣金净收入",
"n_oth_income": "其他经营净收益",
"n_oth_b_income": "加:其他业务净收益",
"prem_income": "保险业务收入",
"out_prem": "减:分出保费",
"une_prem_reser": "提取未到期责任准备金",
"reins_income": "其中:分保费收入",
"n_sec_tb_income": "代理买卖证券业务净收入",
"n_sec_uw_income": "证券承销业务净收入",
"n_asset_mg_income": "受托客户资产管理业务净收入",
"oth_b_income": "其他业务收入",
"fv_value_chg_gain": "加:公允价值变动净收益",
"invest_income": "加:投资净收益",
"ass_invest_income": "其中:对联营企业和合营企业的投资收益",
"forex_gain": "加:汇兑净收益",
"total_cogs": "营业总成本",
"oper_cost": "减:营业成本",
"int_exp": "减:利息支出",
"comm_exp": "减:手续费及佣金支出",
"biz_tax_surchg": "减:营业税金及附加",
"sell_exp": "减:销售费用",
"admin_exp": "减:管理费用",
"fin_exp": "减:财务费用",
"assets_impair_loss": "减:资产减值损失",
"prem_refund": "退保金",
"compens_payout": "赔付总支出",
"reser_insur_liab": "提取保险责任准备金",
"div_payt": "保户红利支出",
"reins_exp": "分保费用",
"oper_exp": "营业支出",
"compens_payout_refu": "减:摊回赔付支出",
"insur_reser_refu": "减:摊回保险责任准备金",
"reins_cost_refund": "减:摊回分保费用",
"other_bus_cost": "其他业务成本",
"operate_profit": "营业利润",
"non_oper_income": "加:营业外收入",
"non_oper_exp": "减:营业外支出",
"nca_disploss": "其中:减:非流动资产处置净损失",
"total_profit": "利润总额",
"income_tax": "所得税费用",
"n_income": "净利润(含少数股东损益)",
"n_income_attr_p": "净利润(不含少数股东损益)",
"minority_gain": "少数股东损益",
"oth_compr_income": "其他综合收益",
"t_compr_income": "综合收益总额",
"compr_inc_attr_p": "归属于母公司(或股东)的综合收益总额",
"compr_inc_attr_m_s": "归属于少数股东的综合收益总额",
"ebit": "息税前利润",
"ebitda": "息税折旧摊销前利润",
"insurance_exp": "保险业务支出",
"undist_profit": "年初未分配利润",
"distable_profit": "可分配利润",
"rd_exp": "研发费用",
"fin_exp_int_exp": "财务费用:利息费用",
"fin_exp_int_inc": "财务费用:利息收入",
"transfer_surplus_rese": "盈余公积转入",
"transfer_housing_imprest": "住房周转金转入",
"transfer_oth": "其他转入",
"adj_lossgain": "调整以前年度损益",
"withdra_legal_surplus": "提取法定盈余公积",
"withdra_legal_pubfund": "提取法定公益金",
"withdra_biz_devfund": "提取企业发展基金",
"withdra_rese_fund": "提取储备基金",
"withdra_oth_ersu": "提取任意盈余公积金",
"workers_welfare": "职工奖金福利",
"distr_profit_shrhder": "可供股东分配的利润",
"prfshare_payable_dvd": "应付优先股股利",
"comshare_payable_dvd": "应付普通股股利",
"capit_comstock_div": "转作股本的普通股股利",
"net_after_nr_lp_correct": "扣除非经常性损益后的净利润(更正前)",
"credit_impa_loss": "信用减值损失",
"net_expo_hedging_benefits": "净敞口套期收益",
"oth_impair_loss_assets": "其他资产减值损失",
"total_opcost": "营业总成本(二)",
"amodcost_fin_assets": "以摊余成本计量的金融资产终止确认收益",
"oth_income": "其他收益",
"asset_disp_income": "资产处置收益",
"continued_net_profit": "持续经营净利润",
"end_net_profit": "终止经营净利润",
"update_flag": "更新标识"
}
# In[11]:
# 定义一个空字典来存储变量名称和描述
variables_dict_2 = {
"ts_code": "TS股票代码",
"ann_date": "公告日期",
"f_ann_date": "实际公告日期",
"end_date": "报告期",
"report_type": "报表类型",
"comp_type": "公司类型(1一般工商业2银行3保险4证券)",
"end_type": "报告期类型",
"total_share": "期末总股本",
"cap_rese": "资本公积金",
"undistr_porfit": "未分配利润",
"surplus_rese": "盈余公积金",
"special_rese": "专项储备",
"money_cap": "货币资金",
"trad_asset": "交易性金融资产",
"notes_receiv": "应收票据",
"accounts_receiv": "应收账款",
"oth_receiv": "其他应收款",
"prepayment": "预付款项",
"div_receiv": "应收股利",
"int_receiv": "应收利息",
"inventories": "存货",
"amor_exp": "待摊费用",
"nca_within_1y": "一年内到期的非流动资产",
"sett_rsrv": "结算备付金",
"loanto_oth_bank_fi": "拆出资金",
"premium_receiv": "应收保费",
"reinsur_receiv": "应收分保账款",
"reinsur_res_receiv": "应收分保合同准备金",
"pur_resale_fa": "买入返售金融资产",
"oth_cur_assets": "其他流动资产",
"total_cur_assets": "流动资产合计",
"fa_avail_for_sale": "可供出售金融资产",
"htm_invest": "持有至到期投资",
"lt_eqt_invest": "长期股权投资",
"invest_real_estate": "投资性房地产",
"time_deposits": "定期存款",
"oth_assets": "其他资产",
"lt_rec": "长期应收款",
"fix_assets": "固定资产",
"cip": "在建工程",
"const_materials": "工程物资",
"fixed_assets_disp": "固定资产清理",
"produc_bio_assets": "生产性生物资产",
"oil_and_gas_assets": "油气资产",
"intan_assets": "无形资产",
"r_and_d": "研发支出",
"goodwill": "商誉",
"lt_amor_exp": "长期待摊费用",
"defer_tax_assets": "递延所得税资产",
"decr_in_disbur": "发放贷款及垫款",
"oth_nca": "其他非流动资产",
"total_nca": "非流动资产合计",
"cash_reser_cb": "现金及存放中央银行款项",
"depos_in_oth_bfi": "存放同业和其它金融机构款项",
"prec_metals": "贵金属",
"deriv_assets": "衍生金融资产",
"rr_reins_une_prem": "应收分保未到期责任准备金",
"rr_reins_outstd_cla": "应收分保未决赔款准备金",
"rr_reins_lins_liab": "应收分保寿险责任准备金",
"rr_reins_lthins_liab": "应收分保长期健康险责任准备金",
"refund_depos": "存出保证金",
"ph_pledge_loans": "保户质押贷款",
"refund_cap_depos": "存出资本保证金",
"indep_acct_assets": "独立账户资产",
"client_depos": "其中:客户资金存款",
"client_prov": "其中:客户备付金",
"transac_seat_fee": "其中:交易席位费",
"invest_as_receiv": "应收款项类投资",
"total_assets": "资产总计",
"lt_borr": "长期借款",
"st_borr": "短期借款",
"cb_borr": "向中央银行借款",
"depos_ib_deposits": "吸收存款及同业存放",
"loan_oth_bank": "拆入资金",
"trading_fl": "交易性金融负债",
"notes_payable": "应付票据",
"acct_payable": "应付账款",
"adv_receipts": "预收款项",
"sold_for_repur_fa": "卖出回购金融资产款",
"comm_payable": "应付手续费及佣金",
"payroll_payable": "应付职工薪酬",
"taxes_payable": "应交税费",
"int_payable": "应付利息",
"div_payable": "应付股利",
"oth_payable": "其他应付款",
"acc_exp": "预提费用",
"deferred_inc": "递延收益",
"st_bonds_payable": "应付短期债券",
"payable_to_reinsurer": "应付分保账款",
"rsrv_insur_cont": "保险合同准备金",
"acting_trading_sec": "代理买卖证券款",
"acting_uw_sec": "代理承销证券款",
"non_cur_liab_due_1y": "一年内到期的非流动负债",
"oth_cur_liab": "其他流动负债",
"total_cur_liab": "流动负债合计",
"bond_payable": "应付债券",
"lt_payable": "长期应付款",
"specific_payables": "专项应付款",
"estimated_liab": "预计负债",
"defer_tax_liab": "递延所得税负债",
"defer_inc_non_cur_liab": "递延收益-非流动负债",
"oth_ncl": "其他非流动负债",
"total_ncl": "非流动负债合计",
"depos_oth_bfi": "同业和其它金融机构存放款项",
"deriv_liab": "衍生金融负债",
"depos": "吸收存款",
"agency_bus_liab": "代理业务负债",
"oth_liab": "其他负债",
"prem_receiv_adva": "预收保费",
"depos_received": "存入保证金",
"ph_invest": "保户储金及投资款",
"reser_une_prem": "未到期责任准备金",
"reser_outstd_claims": "未决赔款准备金",
"reser_lins_liab": "寿险责任准备金",
"reser_lthins_liab": "长期健康险责任准备金",
"indept_acc_liab": "独立账户负债",
"pledge_borr": "其中:质押借款",
"indem_payable": "应付赔付款",
"policy_div_payable": "应付保单红利",
"total_liab": "负债合计",
"treasury_share": "减:库存股",
"ordin_risk_reser": "一般风险准备",
"forex_differ": "外币报表折算差额",
"invest_loss_unconf": "未确认的投资损失",
"minority_int": "少数股东权益",
"total_hldr_eqy_exc_min_int": "股东权益合计(不含少数股东权益)",
"total_hldr_eqy_inc_min_int": "股东权益合计(含少数股东权益)",
"total_liab_hldr_eqy": "负债及股东权益总计",
"lt_payroll_payable": "长期应付职工薪酬",
"oth_comp_income": "其他综合收益",
"oth_eqt_tools": "其他权益工具",
"oth_eqt_tools_p_shr": "其他权益工具(优先股)",
"lending_funds": "融出资金",
"acc_receivable": "应收款项",
"st_fin_payable": "应付短期融资款",
"payables": "应付款项",
"hfs_assets": "持有待售的资产",
"hfs_sales": "持有待售的负债",
"cost_fin_assets": "以摊余成本计量的金融资产",
"fair_value_fin_assets": "以公允价值计量且其变动计入其他综合收益的金融资产",
"cip_total": "在建工程(合计)(元)",
"oth_pay_total": "其他应付款(合计)(元)",
"long_pay_total": "长期应付款(合计)(元)",
"debt_invest": "债权投资(元)",
"oth_debt_invest": "其他债权投资(元)",
"oth_eq_invest": "其他权益工具投资(元)",
"oth_illiq_fin_assets": "其他非流动金融资产(元)",
"oth_eq_ppbond": "其他权益工具:永续债(元)",
"receiv_financing": "应收款项融资",
"use_right_assets": "使用权资产",
"lease_liab": "租赁负债",
"contract_assets": "合同资产",
"contract_liab": "合同负债",
"accounts_receiv_bill": "应收票据及应收账款",
"accounts_pay": "应付票据及应付账款",
"oth_rcv_total": "其他应收款(合计)(元)",
"fix_assets_total": "固定资产(合计)(元)",
"update_flag": "更新标识"
}
# In[12]:
# 定义一个空字典来存储变量名称和描述
variables_dict_3 = {
"ts_code": "TS股票代码",
"ann_date": "公告日期",
"f_ann_date": "实际公告日期",
"end_date": "报告期",
"comp_type": "公司类型(1一般工商业2银行3保险4证券)",
"report_type": "报表类型",
"end_type": "报告期类型",
"net_profit": "净利润",
"finan_exp": "财务费用",
"c_fr_sale_sg": "销售商品、提供劳务收到的现金",
"recp_tax_rends": "收到的税费返还",
"n_depos_incr_fi": "客户存款和同业存放款项净增加额",
"n_incr_loans_cb": "向中央银行借款净增加额",
"n_inc_borr_oth_fi": "向其他金融机构拆入资金净增加额",
"prem_fr_orig_contr": "收到原保险合同保费取得的现金",
"n_incr_insured_dep": "保户储金净增加额",
"n_reinsur_prem": "收到再保业务现金净额",
"n_incr_disp_tfa": "处置交易性金融资产净增加额",
"ifc_cash_incr": "收取利息和手续费净增加额",
"n_incr_disp_faas": "处置可供出售金融资产净增加额",
"n_incr_loans_oth_bank": "拆入资金净增加额",
"n_cap_incr_repur": "回购业务资金净增加额",
"c_fr_oth_operate_a": "收到其他与经营活动有关的现金",
"c_inf_fr_operate_a": "经营活动现金流入小计",
"c_paid_goods_s": "购买商品、接受劳务支付的现金",
"c_paid_to_for_empl": "支付给职工以及为职工支付的现金",
"c_paid_for_taxes": "支付的各项税费",
"n_incr_clt_loan_adv": "客户贷款及垫款净增加额",
"n_incr_dep_cbob": "存放央行和同业款项净增加额",
"c_pay_claims_orig_inco": "支付原保险合同赔付款项的现金",
"pay_handling_chrg": "支付手续费的现金",
"pay_comm_insur_plcy": "支付保单红利的现金",
"oth_cash_pay_oper_act": "支付其他与经营活动有关的现金",
"st_cash_out_act": "经营活动现金流出小计",
"n_cashflow_act": "经营活动产生的现金流量净额",
"oth_recp_ral_inv_act": "收到其他与投资活动有关的现金",
"c_disp_withdrwl_invest": "收回投资收到的现金",
"c_recp_return_invest": "取得投资收益收到的现金",
"n_recp_disp_fiolta": "处置固定资产、无形资产和其他长期资产收回的现金净额",
"n_recp_disp_sobu": "处置子公司及其他营业单位收到的现金净额",
"stot_inflows_inv_act": "投资活动现金流入小计",
"c_pay_acq_const_fiolta": "购建固定资产、无形资产和其他长期资产支付的现金",
"c_paid_invest": "投资支付的现金",
"n_disp_subs_oth_biz": "取得子公司及其他营业单位支付的现金净额",
"oth_pay_ral_inv_act": "支付其他与投资活动有关的现金",
"n_incr_pledge_loan": "质押贷款净增加额",
"stot_out_inv_act": "投资活动现金流出小计",
"n_cashflow_inv_act": "投资活动产生的现金流量净额",
"c_recp_borrow": "取得借款收到的现金",
"proc_issue_bonds": "发行债券收到的现金",
"oth_cash_recp_ral_fnc_act": "收到其他与筹资活动有关的现金",
"stot_cash_in_fnc_act": "筹资活动现金流入小计",
"free_cashflow": "企业自由现金流量",
"c_prepay_amt_borr": "偿还债务支付的现金",
"c_pay_dist_dpcp_int_exp": "分配股利、利润或偿付利息支付的现金",
"incl_dvd_profit_paid_sc_ms": "其中:子公司支付给少数股东的股利、利润",
"oth_cashpay_ral_fnc_act": "支付其他与筹资活动有关的现金",
"stot_cashout_fnc_act": "筹资活动现金流出小计",
"n_cash_flows_fnc_act": "筹资活动产生的现金流量净额",
"eff_fx_flu_cash": "汇率变动对现金的影响",
"n_incr_cash_cash_equ": "现金及现金等价物净增加额",
"c_cash_equ_beg_period": "期初现金及现金等价物余额",
"c_cash_equ_end_period": "期末现金及现金等价物余额",
"c_recp_cap_contrib": "吸收投资收到的现金",
"incl_cash_rec_saims": "其中:子公司吸收少数股东投资收到的现金",
"uncon_invest_loss": "未确认投资损失",
"prov_depr_assets": "加:资产减值准备",
"depr_fa_coga_dpba": "固定资产折旧、油气资产折耗、生产性生物资产折旧",
"amort_intang_assets": "无形资产摊销",
"lt_amort_deferred_exp": "长期待摊费用摊销",
"decr_deferred_exp": "待摊费用减少",
"incr_acc_exp": "预提费用增加",
"loss_disp_fiolta": "处置固定、无形资产和其他长期资产的损失",
"loss_scr_fa": "固定资产报废损失",
"loss_fv_chg": "公允价值变动损失",
"invest_loss": "投资损失",
"decr_def_inc_tax_assets": "递延所得税资产减少",
"incr_def_inc_tax_liab": "递延所得税负债增加",
"decr_inventories": "存货的减少",
"decr_oper_payable": "经营性应收项目的减少",
"incr_oper_payable": "经营性应付项目的增加",
"others": "其他",
"im_net_cashflow_oper_act": "经营活动产生的现金流量净额(间接法)",
"conv_debt_into_cap": "债务转为资本",
"conv_copbonds_due_within_1y": "一年内到期的可转换公司债券",
"fa_fnc_leases": "融资租入固定资产",
"im_n_incr_cash_equ": "现金及现金等价物净增加额(间接法)",
"net_dism_capital_add": "拆出资金净增加额",
"net_cash_rece_sec": "代理买卖证券收到的现金净额(元)",
"credit_impa_loss": "信用减值损失",
"use_right_asset_dep": "使用权资产折旧",
"oth_loss_asset": "其他资产减值损失",
"end_bal_cash": "现金的期末余额",
"beg_bal_cash": "减:现金的期初余额",
"end_bal_cash_equ": "加:现金等价物的期末余额",
"beg_bal_cash_equ": "减:现金等价物的期初余额",
"update_flag": "更新标志(1最新)"
}
def get_f(df):
return df[df['报告期'].str.contains('1231')].reset_index(drop=True)
def Company_Financial_Data(code='',start_date='20160101',end_date='20231231',kind='季度'):
columns1=['公告日期','实际公告日期','报告类型 见底部表','公司类型(1一般工商业2银行3保险4证券)','报告期类型']
income_data = pro.income(ts_code=code, start_date=start_date, end_date=end_date).rename(columns=variables_dict).iloc[:,:-1].drop_duplicates(['报告期']).drop(columns=columns1)
columns2=['公告日期','实际公告日期','报表类型','公司类型(1一般工商业2银行3保险4证券)','报告期类型']
balance_sheet = pro.balancesheet(ts_code=code, start_date=start_date, end_date=end_date).rename(columns=variables_dict_2).iloc[:,:-1].drop_duplicates(['报告期']).drop(columns=columns2)
columns3=['公告日期','实际公告日期','报表类型','公司类型(1一般工商业2银行3保险4证券)','报告期类型']
cash_flow = pro.cashflow(ts_code=code, start_date=start_date, end_date=end_date).rename(columns=variables_dict_3).iloc[:,:-1].drop_duplicates(['报告期']).drop(columns=columns3)
if kind=='年度':
balance_sheet = get_f(balance_sheet)
income_data = get_f(income_data)
cash_flow=get_f(cash_flow)
merged_df = pd.merge(cash_flow, balance_sheet, on='报告期', how='inner', suffixes=('', '_balance'))
# 再次合并时,对 income_data 使用不同的后缀
final_merged_df = pd.merge(merged_df, income_data, on='报告期', how='inner', suffixes=('', '_income'))
# 假设你想保留 cash_flow 中的 'TS股票代码' 列,你可以删除其他重复的 'TS股票代码' 列
final_merged_df=final_merged_df.drop(columns=['TS股票代码_balance', 'TS股票代码_income']).dropna(axis=1, how='any')
return final_merged_df
def Financial_Data_analysis(financial_datas):
financial_data = financial_datas.copy()
# Convert report date to datetime format and extract the year for easier manipulation
try:
financial_data['报告期'] = pd.to_datetime(financial_data['报告期'], format='%Y%m%d')
financial_data['年份'] = financial_data['报告期'].dt.year
except KeyError:
pass # 如果没有 '报告期' 列,跳过
# Calculating the financial ratios
# ROE = Net Income / Shareholder's Equity
try:
if '净利润' in financial_data.columns and '股东权益合计(含少数股东权益)' in financial_data.columns:
financial_data['净资产收益率'] = financial_data['净利润'] / financial_data['股东权益合计(含少数股东权益)']
elif '净利润(含少数股东损益)' in financial_data.columns and '股东权益合计(含少数股东权益)' in financial_data.columns:
financial_data['净资产收益率'] = financial_data['净利润(含少数股东损益)'] / financial_data['股东权益合计(含少数股东权益)']
except KeyError:
pass # 如果所需列缺失,跳过
# ROA = Net Income / Total Assets
try:
if '净利润' in financial_data.columns and '资产总计' in financial_data.columns:
financial_data['总资产报酬率'] = financial_data['净利润'] / financial_data['资产总计']
elif '净利润(含少数股东损益)' in financial_data.columns and '资产总计' in financial_data.columns:
financial_data['总资产报酬率'] = financial_data['净利润(含少数股东损益)'] / financial_data['资产总计']
except KeyError:
pass # 如果所需列缺失,跳过
# EBIT = Net Income + Income Tax + Financial Expenses
try:
if '净利润' in financial_data.columns and '所得税费用' in financial_data.columns and '财务费用' in financial_data.columns:
financial_data['EBIT'] = financial_data['净利润'] + financial_data['所得税费用'] + financial_data['财务费用']
except KeyError:
pass # 如果所需列缺失,跳过
# Receivables Turnover Ratio = Operating Revenue / Average Receivables
try:
if '营业收入' in financial_data.columns and '应收账款' in financial_data.columns:
financial_data['应收账款周转率'] = financial_data['营业收入'] / financial_data['应收账款']
except KeyError:
pass # 如果所需列缺失,跳过
# Debt to Asset Ratio = Total Liabilities / Total Assets
try:
if '负债合计' in financial_data.columns and '资产总计' in financial_data.columns:
financial_data['资产负债率'] = financial_data['负债合计'] / financial_data['资产总计']
except KeyError:
pass # 如果所需列缺失,跳过
# Quick Ratio = (Cash + Receivables) / Current Liabilities
try:
if '货币资金' in financial_data.columns and '应收账款' in financial_data.columns and '流动负债合计' in financial_data.columns:
financial_data['速动比率'] = (financial_data['货币资金'] + financial_data['应收账款']) / financial_data['流动负债合计']
except KeyError:
pass # 如果所需列缺失,跳过
# Inventory Turnover Ratio = Cost of Goods Sold / Average Inventory
try:
if '营业总成本' in financial_data.columns and '存货' in financial_data.columns:
financial_data['存货周转率'] = financial_data['营业总成本'] / financial_data['存货']
except KeyError:
pass # 如果所需列缺失,跳过
# Calculating Yearly Growth Rates for Sales and Operating Profit
try:
financial_data_sorted = financial_data.sort_values(by=['TS股票代码', '年份'])
if '营业收入' in financial_data_sorted.columns:
financial_data_sorted['销售增长率'] = financial_data_sorted.groupby('TS股票代码')['营业收入'].pct_change()
if '营业利润' in financial_data_sorted.columns:
financial_data_sorted['销售利润增长率'] = financial_data_sorted.groupby('TS股票代码')['营业利润'].pct_change()
except KeyError:
pass # 如果所需列缺失,跳过
# Recalculate ROA with the adjusted formula
try:
if 'EBIT' in financial_data_sorted.columns and '资产总计' in financial_data_sorted.columns:
financial_data_sorted['总资产报酬率'] = financial_data_sorted['EBIT'] / financial_data_sorted['资产总计']
except KeyError:
pass # 如果所需列缺失,跳过
# Sales Gross Margin = (Operating Revenue - Operating Cost) / Operating Revenue
try:
if '营业总收入' in financial_data_sorted.columns and '营业总成本' in financial_data_sorted.columns:
financial_data_sorted['销售毛利率'] = (financial_data_sorted['营业总收入'] - financial_data_sorted['营业总成本']) / financial_data_sorted['营业总收入']
except KeyError:
pass # 如果所需列缺失,跳过
# 流动比率
try:
if '流动资产合计' in financial_data_sorted.columns and '流动负债合计' in financial_data_sorted.columns:
financial_data_sorted['流动比率'] = financial_data_sorted['流动资产合计'] / financial_data_sorted['流动负债合计']
except KeyError:
pass # 如果所需列缺失,跳过
# Selecting columns to display
columns_to_display = ['TS股票代码', '年份', '净资产收益率', '总资产报酬率', '应收账款周转率', '资产负债率', '速动比率', '销售增长率', '销售利润增长率', '存货周转率', '总资产报酬率',
'销售毛利率', '流动比率', '资产收益率']
financial_ratios = financial_data_sorted[[i for i in columns_to_display if i in financial_data_sorted.columns]]
return financial_ratios
import tushare as ts
import pandas as pd
import streamlit as st # 导入Streamlit库
# Tushare API
api_key = '7d*************************************************5'
ts.set_token(api_key)
pro = ts.pro_api()
# 用户认证信息
st.write(pro.user(token=api_key))
st.write('如果你看到2k以上积分,就有权限')
def read_file_to_list(file_path):
try:
with open(file_path, 'r', encoding='utf-8') as file:
content_list = [item.strip() for item in file.read().split(',') if item.strip()]
st.success('读取关键词成功')
return content_list
except FileNotFoundError:
st.error(f"文件 {file_path} 未找到。")
return []
except Exception as e:
st.error(f"读取文件时发生错误:{e}")
return []
# Streamlit 输入框
st.title("财务数据获取与分析")
# 使用 Streamlit tabs 来分隔不同界面
tab1, tab2 = st.tabs(["财务数据下载", "财务数据分析"])
with tab1:
# 股票名称输入框,用户输入英文逗号分割的股票名称,自动去除空格
stock_input = st.text_input('请输入股票名称(英文逗号分隔)', '贵州茅台,格力电器')
codes_names = [code.strip() for code in stock_input.split(',') if code.strip()]
st.write("选择的行业/股票:", codes_names)
# 日期选择框
start_date = st.text_input('请输入开始年份(例如:“2022”)', '2022')
end_date = st.text_input('请输入结束年份(例如:“2025”)', '2025')
start_date = start_date + '0101'
end_date = end_date + '1231'
# 财务数据的年度/季度选择
kind = st.selectbox("选择财务数据类型", ["年度", "季度"])
# 使用 Streamlit 按钮来控制代码执行
run_button = st.button('开始获取上述公司财务数据')
if run_button:
# 获取股票列表
data = pro.stock_basic(exchange='', list_status='L', fields='ts_code,symbol,name,area,industry,list_date')
codes = []
for codes_name in codes_names:
try:
longbai_code = data[data['name'].str.contains(codes_name)]['ts_code'].to_numpy()
codes.append(longbai_code[0])
st.write(f'{codes_name}的股票代码是:{longbai_code[0]}')
except IndexError:
st.write(f'无法查询到{codes_name}对应的代码,请检查名称')
st.write(f"\n获取上述查询到代码的股票从{start_date}开始到{end_date}结束的财务数据")
st.markdown("<hr style='border: 1px solid blue;'>", unsafe_allow_html=True)
# 获取财务数据并保存
with pd.ExcelWriter('上市公司财务数据.xlsx', engine='xlsxwriter') as writer:
for code in codes:
st.write(f'{code}财务数据储存成功')
df = Company_Financial_Data(code=code, start_date=start_date, end_date=end_date, kind=kind)
df.to_excel(writer, sheet_name=code, index=False)
st.write("刚刚下载好的财务数据文件为:上市公司财务数据.xlsx")
with tab2:
# 财务数据分析
calculate = st.checkbox("是否进行财务指标的计算?")
if calculate:
file_name = st.text_input('请输入刚刚下载的数据的表名', '上市公司财务数据.xlsx')
xls = pd.ExcelFile(f'{file_name}')
sheet_names = xls.sheet_names
xls.close()
with pd.ExcelWriter('财务数据计算的指标.xlsx', engine='xlsxwriter') as writer:
for sheet_name in sheet_names:
df = pd.DataFrame()
financial_datas = pd.read_excel('上市公司财务数据.xlsx', sheet_name=sheet_name)
df1 = Financial_Data_analysis(financial_datas)
df = pd.concat([df, df1], axis=0, ignore_index=True)
df.to_excel(writer, sheet_name=sheet_name, index=False)
st.success("财务数据计算完成,结果已保存到:财务数据计算的指标.xlsx里面")
代码很长,毕竟是一个应用的代码,全都在这一个文件里面了。我们把这段代码放入 “财务数据.py”文件中,然后再新建一个 ‘财务数据接口程序.py’ 文件,写入下面代码:
import streamlit.web.cli as stcli
import os,sys
def get_base_path():
"""获取脚本运行的基础路径,支持 PyInstaller 打包"""
if getattr(sys, 'frozen', False): # 如果是 PyInstaller 打包的环境
return sys._MEIPASS # 获取临时目录路径
return os.path.dirname(__file__) # 普通运行环境
# 获取 QZCA_AI.py 的路径(适配打包环境) ###注意这里要改成你自己的应用py文件的名称
script_path = os.path.join(get_base_path(), "财务数据.py")
def resolve_path(path):
"""解析相对路径为绝对路径"""
resolved_path = os.path.abspath(os.path.join(os.getcwd(), path))
return resolved_path
if __name__ == "__main__":
# 检查 QZCA_AI.py 是否存在
if not os.path.exists(script_path):
print(f"Error: The script '{script_path}' does not exist!")
sys.exit(1)
# 构造 Streamlit 命令
sys.argv = [
"streamlit",
"run",
script_path, # 替换为解析后的路径
"--global.developmentMode=false",
]
try:
sys.exit(stcli.main())
except Exception as e:
print(f"Error while running Streamlit: {e}")
sys.exit(1)
双击 ‘财务数据接口程序.py’ 文件 ,就可以运行了。
下面学习怎么打包。
streamlit打包
咱们首先创建一个hooks文件夹,在下面创建一个python文件(我的叫hook-streamlit.py),代码如下:
from PyInstaller.utils.hooks import copy_metadata
datas = copy_metadata("streamlit")
准备好这三个文件,然后咱们先打包第一次:
(是在财务数据接口程序.py文件夹目录下面打包)
打包命令如下,:
在这个工作目录下,打开cmd输入(如果环境在conda里面就行打开anaconda 的prompt命令提示符):
pyinstaller --onefile --additional-hooks-dir=./hooks 财务数据接口程序.py --clean
然后等待打包:
然后就会生成上面的 财务数据接口程序.spec 这个文件,咱们先将这时候的dist和build文件删掉。
可选 :
我们可以对我们的应用加个图表,从而更加好看一些。准备一张图片,然后用下面的网站转化为ico文件。
准备好后将你的 .ico文件 放在项目目录下。
打开财务数据接口程序.spec文件(自带的记事本就可以打开),编辑下面部分
# -*- mode: python ; coding: utf-8 -*-
#添加下面部分
from PyInstaller.utils.hooks import collect_data_files
from PyInstaller.utils.hooks import copy_metadata
### 这里改成自己的python包的路径
datas = [("C:/Users/qzca/AppData/Local/Programs/Python/Python311/Lib/site-packages/streamlit/runtime","./streamlit/runtime") ,
("./财务数据.py", "./")]
datas += collect_data_files("streamlit")
datas += copy_metadata("streamlit")
excludes = [
"tkinter", # 排除 GUI 模块
"unittest", # 排除测试模块
# "pydoc", # 排除文档生成模块
# "http", # 排除 HTTP 相关模块
"sqlite3", # 排除 SQLite 数据库模块
# "multiprocessing", # 排除多进程模块(如果不需要)
'transformers','jupyte','conda','FuzzyTM','Faker',
# "numpy", # 如果不需要 numpy
"scipy", # 如果不需要 scipy
"matplotlib", # 如果不需要 matplotlib
'searbon','xgboost','akshare','yfinance'
]
a = Analysis(
['财务数据接口程序.py'],
pathex=[],
binaries=[],
datas=datas, ### 改这里,还有需要的包都放在下面
hiddenimports=['pandas','tushare'],
hookspath=['./hooks'],
hooksconfig={},
runtime_hooks=[],
excludes=excludes,
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='财务数据接口程序',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
# 这里添加ico文件
icon='fm.ico',
)
里面的datas里面的安装包的路径要改成你自己安装的路径(代码里面是我的路径),你可以通过Python里面的cmd命令(pip show streamlit)去找到你的streamlit包安装在哪个文件夹(或者是环境在anaconda里面就conda命令),然后打开这个文件夹复制路径就可以了。
然后确认无误以后就开始咱们的第二次打包。
输入以下指令:
pyinstaller 财务数据接口程序.spec --clean
然后会在dist文件夹下面,生成的财务数据接口获取软件.exe文件,
点击exe文件运行即可,出现下面这个页面就是成功了:
就会弹出浏览器的界面里面去获取财务数据就可以了:
这样就可以带着这个exe文件,无论什么window电脑都可以下载财务数据了,当然需要互联网。