{ "cells": [ { "cell_type": "code", "id": "initial_id", "metadata": { "collapsed": true, "ExecuteTime": { "end_time": "2025-01-11T03:30:00.044697Z", "start_time": "2025-01-11T03:30:00.041372Z" } }, "source": [ "import pandas as pd\n", "import tushare as ts\n", "\n", "ts_pro = ts.pro_api(token=\"64ebff4fa679167600b905ee45dd88e76f3963c0ff39157f3f085f0e\")" ], "outputs": [], "execution_count": 25 }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-09T06:28:32.524630Z", "start_time": "2025-01-09T06:27:15.688831Z" } }, "cell_type": "code", "source": [ "# 从1989年开始循环年份\n", "for year in range(2000, 2024):\n", " # ts_pro.balancesheet_vip(period=f\"{year}1231\").to_csv(f\"../temp/财务报表/资产负债表/{year}.csv\")\n", " # ts_pro.cashflow_vip(period=f\"{year}1231\").to_csv(f\"../temp/财务报表/现金流量表/{year}.csv\")\n", " # ts_pro.income_vip(period=f\"{year}1231\").to_csv(f\"../temp/财务报表/利润表/{year}.csv\")\n", " ts_pro.fina_indicator_vip(period=f\"{year}1231\").to_csv(f\"../temp/财务报表/财务指标/{year}.csv\")\n", " # ts_pro.fina_audit(period=f\"{year}1231\").to_csv(f\"../temp/财务报表/审计意见/{year}.csv\")" ], "id": "b03b118c70b21315", "outputs": [], "execution_count": 15 }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-10T03:01:43.076024Z", "start_time": "2025-01-10T03:01:42.644700Z" } }, "cell_type": "code", "source": [ "df_income = ts_pro.income(ts_code=\"600519.SH\", period=\"20231231\", fields=\"ts_code,end_date,n_income\")\n", "df_balancesheet = ts_pro.balancesheet(ts_code=\"600519.SH\", period=\"20231231\",\n", " fields=\"ts_code,end_date,total_hldr_eqy_exc_min_int\")\n", "merged_df = pd.merge(df_income, df_balancesheet, on=['ts_code', 'end_date'])\n", "merged_df['roe'] = merged_df['n_income'] / merged_df['total_hldr_eqy_exc_min_int']\n", "merged_df" ], "id": "575590399bf15e70", "outputs": [ { "data": { "text/plain": [ " ts_code end_date n_income total_hldr_eqy_exc_min_int roe\n", "0 600519.SH 20231231 7.752148e+10 2.156686e+11 0.359447" ], "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ts_codeend_daten_incometotal_hldr_eqy_exc_min_introe
0600519.SH202312317.752148e+102.156686e+110.359447
\n", "
" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 31 }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-10T02:59:32.764968Z", "start_time": "2025-01-10T02:59:32.601657Z" } }, "cell_type": "code", "source": "ts_pro.fina_indicator(ts_code=\"600519.SH\", period=\"20231231\")[\"roe\"]", "id": "d59f62a613379fbd", "outputs": [ { "data": { "text/plain": [ "0 36.1755\n", "Name: roe, dtype: float64" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 26 }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-10T04:01:33.511246Z", "start_time": "2025-01-10T04:01:33.382955Z" } }, "cell_type": "code", "source": "ts_pro.income(ts_code='600519.SH', start_date='20220101', end_date='20241231', fields='end_date,n_income')", "id": "c43925cfb5552cd9", "outputs": [ { "data": { "text/plain": [ " end_date n_income\n", "0 20240930 6.303146e+10\n", "1 20240630 4.317691e+10\n", "2 20240331 2.488235e+10\n", "3 20231231 7.752148e+10\n", "4 20230930 5.482717e+10\n", "5 20230630 3.733197e+10\n", "6 20230331 2.152473e+10\n", "7 20221231 6.537514e+10\n", "8 20221231 6.537514e+10\n", "9 20220930 4.631399e+10\n", "10 20220630 3.110536e+10\n", "11 20220331 1.795212e+10\n", "12 20211231 5.572053e+10\n", "13 20211231 5.572053e+10" ], "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
end_daten_income
0202409306.303146e+10
1202406304.317691e+10
2202403312.488235e+10
3202312317.752148e+10
4202309305.482717e+10
5202306303.733197e+10
6202303312.152473e+10
7202212316.537514e+10
8202212316.537514e+10
9202209304.631399e+10
10202206303.110536e+10
11202203311.795212e+10
12202112315.572053e+10
13202112315.572053e+10
\n", "
" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 40 }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-10T04:17:56.196027Z", "start_time": "2025-01-10T04:17:55.879469Z" } }, "cell_type": "code", "source": [ "# 获取净利润\n", "income_df = ts_pro.income(ts_code='600519.SH', start_date='20220101', end_date='20241231', fields='end_date,n_income')\n", "net_profit = income_df[income_df['end_date'] == '20231231']['n_income'].values[0]\n", "\n", "# 获取期初和期末的股东权益和总资产\n", "balancesheet_df = ts_pro.balancesheet(ts_code='600519.SH', start_date='20220101', end_date='20241231',\n", " fields='end_date,total_hldr_eqy_exc_min_int,total_assets')\n", "eqy_initial = balancesheet_df[balancesheet_df['end_date'] == '20230331']['total_hldr_eqy_exc_min_int'].values[0]\n", "eqy_final = balancesheet_df[balancesheet_df['end_date'] == '20231231']['total_hldr_eqy_exc_min_int'].values[0]\n", "total_assets_initial = balancesheet_df[balancesheet_df['end_date'] == '20230331']['total_assets'].values[0]\n", "total_assets_final = balancesheet_df[balancesheet_df['end_date'] == '20231231']['total_assets'].values[0]\n", "\n", "# 计算平均股东权益和平均总资产\n", "avg_eqy = (eqy_initial + eqy_final) / 2\n", "avg_assets = (total_assets_initial + total_assets_final) / 2\n", "\n", "# 计算ROE和ROA\n", "roe = net_profit / avg_eqy\n", "roa = net_profit / avg_assets\n", "\n", "print(f'ROE: {roe:.4f}')\n", "print(f'ROA: {roa:.4f}')" ], "id": "caf1a1555d4c972e", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ROE: 0.3573\n", "ROA: 0.2919\n" ] } ], "execution_count": 43 }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-10T04:19:57.750533Z", "start_time": "2025-01-10T04:19:57.531524Z" } }, "cell_type": "code", "source": [ "# 获取营业收入净额\n", "income_df = ts_pro.income(ts_code='600519.SH', start_date='20220101', end_date='20241231', fields='end_date,revenue')\n", "revenue = income_df[income_df['end_date'] == '20231231']['revenue'].values[0]\n", "\n", "# 获取期初(上一年12月31日)和期末(当前年12月31日)的总资产\n", "balancesheet_df = ts_pro.balancesheet(ts_code='600519.SH', start_date='20220101', end_date='20241231',\n", " fields='end_date,total_assets')\n", "total_assets_initial = balancesheet_df[balancesheet_df['end_date'] == '20221231']['total_assets'].values[0]\n", "total_assets_final = balancesheet_df[balancesheet_df['end_date'] == '20231231']['total_assets'].values[0]\n", "\n", "# 计算平均总资产\n", "avg_assets = (total_assets_initial + total_assets_final) / 2\n", "\n", "# 计算总资产周转率\n", "total_asset_turnover = revenue / avg_assets\n", "\n", "print(f'总资产周转率: {total_asset_turnover:.4f}')" ], "id": "49488c6640beb4ed", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "总资产周转率: 0.5604\n" ] } ], "execution_count": 48 }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-10T04:23:50.762070Z", "start_time": "2025-01-10T04:23:50.585818Z" } }, "cell_type": "code", "source": [ "# 获取期末的现金及现金等价物和总资产\n", "balancesheet_df = ts_pro.balancesheet(ts_code='600519.SH', start_date='20220101', end_date='20241231',\n", " fields='end_date, money_cap, total_assets')\n", "cash_and_equivalents = balancesheet_df[balancesheet_df['end_date'] == '20231231']['money_cap'].values[0]\n", "total_assets = balancesheet_df[balancesheet_df['end_date'] == '20231231']['total_assets'].values[0]\n", "\n", "# 计算现金和现金等价物总和占总资产的比率\n", "cash_ratio = cash_and_equivalents / total_assets\n", "\n", "print(f'现金和现金等价物总和占总资产的比率: {cash_ratio:.4f}')" ], "id": "526ef46373e1c8fe", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "现金和现金等价物总和占总资产的比率: 0.2533\n" ] } ], "execution_count": 49 }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-10T04:27:11.461667Z", "start_time": "2025-01-10T04:27:11.160878Z" } }, "cell_type": "code", "source": [ "# 获取营业收入\n", "income_df = ts_pro.income(ts_code='600519.SH', start_date='20220101', end_date='20241231', fields='end_date, revenue')\n", "revenue = income_df[income_df['end_date'] == '20231231']['revenue'].values[0]\n", "\n", "# 获取期初和期末的应收账款\n", "balancesheet_df = ts_pro.balancesheet(ts_code='600519.SH', start_date='20220101', end_date='20241231',\n", " fields='end_date, accounts_receiv')\n", "accounts_receiv_initial = balancesheet_df[balancesheet_df['end_date'] == '20221231']['accounts_receiv'].values[0]\n", "accounts_receiv_final = balancesheet_df[balancesheet_df['end_date'] == '20231231']['accounts_receiv'].values[0]\n", "\n", "# 计算平均应收账款余额\n", "avg_accounts_receiv = (accounts_receiv_initial + accounts_receiv_final) / 2\n", "\n", "# 计算应收账款周转率\n", "accounts_receiv_turnover = revenue / avg_accounts_receiv\n", "\n", "# 计算收现日数\n", "collection_period = 365 / accounts_receiv_turnover\n", "\n", "print(f'收现日数: {collection_period:.2f} 天')" ], "id": "dca87ef21cf425ee", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "收现日数: 0.10 天\n" ] } ], "execution_count": 50 }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-10T07:10:09.564888Z", "start_time": "2025-01-10T07:10:08.771019Z" } }, "cell_type": "code", "source": [ "code = \"000672.SZ\"\n", "year = \"2023\"\n", "period = f\"{year}1231\"\n", "last_period = f\"{int(year) - 1}1231\"\n", "\n", "balancesheet_fields = \"total_assets,total_hldr_eqy_inc_min_int,money_cap,accounts_receiv,inventories\"\n", "balancesheet_df = ts_pro.balancesheet(ts_code=code, period=period, fields=balancesheet_fields)\n", "last_balancesheet_df = ts_pro.balancesheet(ts_code=code, period=last_period, fields=balancesheet_fields)\n", "\n", "income_fields = \"n_income,revenue,total_revenue,oper_cost,operate_profit,total_opcost\"\n", "income_df = ts_pro.income(ts_code=code, period=period, fields=income_fields)\n", "last_income_df = ts_pro.income(ts_code=code, period=last_period, fields=income_fields)\n", "\n", "cashflow_fields = \"cash_paid_for_trade_fin\"\n", "cashflow_df = ts_pro.cashflow(ts_code=code, period=period, fields=cashflow_fields)\n", "last_cashflow_df = ts_pro.cashflow(ts_code=code, period=last_period, fields=cashflow_fields)" ], "id": "524a18f138a84f4a", "outputs": [], "execution_count": 96 }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-10T07:10:35.283014Z", "start_time": "2025-01-10T07:10:35.268876Z" } }, "cell_type": "code", "source": [ "# ROE & ROA\n", "roe = income_df[\"n_income\"].values[0] / ((balancesheet_df[\"total_hldr_eqy_inc_min_int\"].values[0] +\n", " last_balancesheet_df[\"total_hldr_eqy_inc_min_int\"].values[0]) / 2)\n", "roa = income_df[\"n_income\"].values[0] / (\n", " (balancesheet_df[\"total_assets\"].values[0] + last_balancesheet_df[\"total_assets\"].values[0]) / 2)\n", "print(f\"ROE: {roe:.4f}\")\n", "print(f\"ROA: {roa:.4f}\")\n", "\n", "# 净利润(转换为百万为单位)\n", "net_profit = income_df[\"n_income\"].values[0] / 1000000\n", "print(f\"净利润: {net_profit:.4f}百万\")\n", "\n", "# 总资产周转率\n", "total_asset_turnover = income_df[\"total_revenue\"].values[0] / (\n", " (balancesheet_df[\"total_assets\"].values[0] + last_balancesheet_df[\"total_assets\"].values[0]) / 2)\n", "print(f\"总资产周转率: {total_asset_turnover:.4f}\")\n", "\n", "# 现金比率\n", "cash_ratio = + balancesheet_df[\"money_cap\"].values[0] / balancesheet_df[\"total_assets\"].values[0]\n", "print(f\"现金比率: {cash_ratio:.4f}\")\n", "\n", "# 收现日数\n", "collection_period = 360 / (income_df[\"total_revenue\"].values[0] / balancesheet_df[\"accounts_receiv\"].values[0])\n", "print(f\"收现日数: {collection_period:.2f} 天\")\n", "\n", "# 销货日数\n", "sales_period = 360 / ((income_df[\"total_revenue\"].values[0]) / balancesheet_df[\"inventories\"].values[0])\n", "print(f\"销货日数: {sales_period:.2f} 天\")\n", "\n", "# 毛利率\n", "gross_profit_margin = (income_df[\"total_revenue\"].values[0] - income_df[\"oper_cost\"].values[0]) / income_df[\n", " \"revenue\"].values[0]\n", "print(f\"毛利率: {gross_profit_margin:.4f}\")\n", "\n", "# 经营利润率\n", "operating_profit_margin = income_df[\"operate_profit\"].values[0] / income_df[\"total_revenue\"].values[0]\n", "print(f\"经营利润率: {operating_profit_margin:.4f}\")\n", "print(f\"经营安全边际率: {(operating_profit_margin / gross_profit_margin):.4f}\")" ], "id": "8707ca42171475a8", "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ROE: 0.0747\n", "ROA: 0.0411\n", "净利润: 701.3791百万\n", "总资产周转率: 0.3745\n", "现金比率: 0.2253\n", "收现日数: 12.95 天\n", "销货日数: 59.70 天\n", "毛利率: 0.2775\n", "经营利润率: 0.1474\n", "经营安全边际率: 0.5312\n" ] } ], "execution_count": 98 }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-11T03:51:41.253282Z", "start_time": "2025-01-11T03:51:41.243498Z" } }, "cell_type": "code", "source": [ "def get_blancesheet_df(start_year, end_year):\n", " fields = [\"ts_code\", \"end_date\", \"total_assets\", \"total_hldr_eqy_inc_min_int\", \"money_cap\", \"accounts_receiv\",\n", " \"inventories\"]\n", " result = pd.DataFrame(columns=fields)\n", " for year in range(start_year, end_year + 1):\n", " period = f\"{year}1231\"\n", " temp = ts_pro.balancesheet_vip(period=period, fields=\",\".join(fields))\n", " result = pd.concat([result, temp], ignore_index=True)\n", " return result\n", "\n", "def get_income_df(start_year, end_year):\n", " fields = [\"ts_code\", \"end_date\", \"n_income\", \"revenue\", \"total_revenue\", \"oper_cost\", \"operate_profit\", \"total_opcost\"]\n", " result = pd.DataFrame(columns=fields)\n", " for year in range(start_year, end_year + 1):\n", " period = f\"{year}1231\"\n", " temp = ts_pro.income_vip(period=period, fields=\",\".join(fields))\n", " result = pd.concat([result, temp], ignore_index=True)\n", " return result\n", "\n", "def clean_df(df):\n", " df = df.drop_duplicates(subset=[\"ts_code\", \"end_date\"])\n", " df[\"end_date\"] = df[\"end_date\"].str[:4]\n", " return df" ], "id": "6d90bcb4c5151976", "outputs": [], "execution_count": 54 }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-11T03:51:53.799229Z", "start_time": "2025-01-11T03:51:42.756645Z" } }, "cell_type": "code", "source": [ "blancesheet_df = clean_df(get_blancesheet_df(2018, 2024))\n", "income_df = clean_df(get_income_df(2018, 2024))" ], "id": "9d7013cff65167ed", "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/var/folders/7h/w0cmp4zj6mn9br_6nyj310m40000gn/T/ipykernel_39014/3037579022.py:8: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation.\n", " result = pd.concat([result, temp], ignore_index=True)\n", "/var/folders/7h/w0cmp4zj6mn9br_6nyj310m40000gn/T/ipykernel_39014/3037579022.py:8: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation.\n", " result = pd.concat([result, temp], ignore_index=True)\n", "/var/folders/7h/w0cmp4zj6mn9br_6nyj310m40000gn/T/ipykernel_39014/3037579022.py:17: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation.\n", " result = pd.concat([result, temp], ignore_index=True)\n", "/var/folders/7h/w0cmp4zj6mn9br_6nyj310m40000gn/T/ipykernel_39014/3037579022.py:17: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation.\n", " result = pd.concat([result, temp], ignore_index=True)\n" ] } ], "execution_count": 55 }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-11T04:06:53.483655Z", "start_time": "2025-01-11T04:06:53.417743Z" } }, "cell_type": "code", "source": [ "stock_df = pd.merge(blancesheet_df, income_df, on=[\"ts_code\", \"end_date\"])\n", "test_df = stock_df[stock_df[\"ts_code\"] == \"000672.SZ\"].copy()\n", "test_df[\"roe\"] = test_df[\"n_income\"] / ((test_df[\"total_hldr_eqy_inc_min_int\"] +\n", " test_df[\"total_hldr_eqy_inc_min_int\"].shift(1)) / 2)\n", "test_df[[\"ts_code\",\"end_date\",\"roe\"]]\n", "# stock_group = income_df.groupby('ts_code')\n", "# stock_group.get_group(\"000672.SZ\")" ], "id": "f9317a2d18449db2", "outputs": [ { "data": { "text/plain": [ " ts_code end_date roe\n", "3346 000672.SZ 2018 NaN\n", "8529 000672.SZ 2019 0.508885\n", "12623 000672.SZ 2020 0.316230\n", "17853 000672.SZ 2021 0.278297\n", "22036 000672.SZ 2022 0.105235\n", "28907 000672.SZ 2023 0.074670" ], "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
ts_codeend_dateroe
3346000672.SZ2018NaN
8529000672.SZ20190.508885
12623000672.SZ20200.316230
17853000672.SZ20210.278297
22036000672.SZ20220.105235
28907000672.SZ20230.074670
\n", "
" ] }, "execution_count": 68, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 68 } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.6" } }, "nbformat": 4, "nbformat_minor": 5 }