{ "cells": [ { "cell_type": "code", "id": "initial_id", "metadata": { "collapsed": true, "ExecuteTime": { "end_time": "2025-01-13T03:10:01.926908Z", "start_time": "2025-01-13T03:10:01.923521Z" } }, "source": [ "import pandas as pd\n", "import tushare as ts\n", "\n", "ts_pro = ts.pro_api(token=\"64ebff4fa679167600b905ee45dd88e76f3963c0ff39157f3f085f0e\")" ], "outputs": [], "execution_count": 182 }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-13T03:10:03.759538Z", "start_time": "2025-01-13T03:10:02.003985Z" } }, "cell_type": "code", "source": [ "# 加载股票信息\n", "stock_df = pd.read_csv(\"../材料/股票基础信息.csv\")\n", "# 加载财报信息\n", "source_finance_df = pd.read_csv(\"../temp/finance.csv\")\n", "finance_df = pd.DataFrame()\n", "finance_df[[\n", " \"code\",\n", " # 年份\n", " \"year\",\n", " # 股东权益合计(含少数股东权益)\n", " \"total_stockholder_interest\",\n", " # 净利润\n", " \"net_income\",\n", " # 总资产\n", " \"total_assets\",\n", " # 营业总收入\n", " \"total_revenue\",\n", " # 存货\n", " \"inventories\",\n", " # 应收账款\n", " \"accounts_receivable\",\n", " # 营业成本\n", " \"operating_costs\",\n", " # 营业利润\n", " \"operating_profit\",\n", " # 现金与现金等价物\n", " \"cash\",\n", " # 营业活动现金流量净值\n", " \"operating_net_cash_flow\",\n", "]] = source_finance_df[[\n", " \"ts_code\",\n", " \"end_date\",\n", " \"total_hldr_eqy_inc_min_int\",\n", " \"n_income\",\n", " \"total_assets\",\n", " \"total_revenue\",\n", " \"inventories\",\n", " \"accounts_receiv\",\n", " \"oper_cost\",\n", " \"operate_profit\",\n", " \"money_cap\",\n", " \"n_cashflow_act\",\n", "]]" ], "id": "68b2debc14502fd5", "outputs": [], "execution_count": 183 }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-13T03:10:03.773392Z", "start_time": "2025-01-13T03:10:03.761918Z" } }, "cell_type": "code", "source": "finance_df[finance_df[\"code\"] == \"600763.SH\"][[\"year\", \"net_income\"]]", "id": "f0e8942b3403348c", "outputs": [ { "data": { "text/plain": [ " year net_income\n", "2979 2014 1.138340e+08\n", "7615 2015 1.936414e+08\n", "12121 2016 1.328421e+08\n", "16405 2017 2.266875e+08\n", "21964 2018 3.592014e+08\n", "25657 2019 5.077704e+08\n", "29113 2020 5.449616e+08\n", "36313 2021 7.861501e+08\n", "40855 2022 6.156781e+08\n", "45977 2023 5.784234e+08" ], "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", "
yearnet_income
297920141.138340e+08
761520151.936414e+08
1212120161.328421e+08
1640520172.266875e+08
2196420183.592014e+08
2565720195.077704e+08
2911320205.449616e+08
3631320217.861501e+08
4085520226.156781e+08
4597720235.784234e+08
\n", "
" ] }, "execution_count": 184, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 184 }, { "metadata": {}, "cell_type": "markdown", "source": "过滤上市时间大于5年的企业,由于计算很多数值需要与前一年比,所以实际上需要的是上市时间至少6年的企业", "id": "3052b8c4442f3643" }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-13T03:10:03.784454Z", "start_time": "2025-01-13T03:10:03.774686Z" } }, "cell_type": "code", "source": [ "from datetime import datetime\n", "\n", "select_df = stock_df[[\"ts_code\", \"list_date\"]]\n", "select_df.loc[:, \"list_date\"] = pd.to_datetime(select_df[\"list_date\"], format=\"%Y%m%d\").dt.year\n", "select_df = select_df[select_df[\"list_date\"] < datetime.now().year - 6]\n", "codes = select_df[\"ts_code\"].tolist()\n", "codes = map(lambda x: [x, stock_df[stock_df[\"ts_code\"] == x][\"name\"].values[0], 0], codes)" ], "id": "4293bd93ea8f9ed", "outputs": [], "execution_count": 185 }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-13T03:10:03.789557Z", "start_time": "2025-01-13T03:10:03.786826Z" } }, "cell_type": "code", "source": [ "def add_score(code_list, score):\n", " code_list[2] = code_list[2] + score\n", " code_list.append(score)\n", " return code_list" ], "id": "fa22f7c620511f0a", "outputs": [], "execution_count": 186 }, { "metadata": {}, "cell_type": "markdown", "source": [ "ROE\n", "\n", "股东权益报酬率(%) RoE\t股东权益报酬率RoE 是判断股票是否具备”长期上涨潜力“最重要的指标之一, RoE 如果既稳定又优秀,那这家公司的其他指标也基本不会差。\n", "RoE均值 >= 35\t550分\n", "35 > RoE均值 >= 30\t500分\n", "30 > RoE均值 >= 25\t450分\n", "25 > RoE均值 >= 20\t400分\n", "20 > RoE均值 >= 15\t300分\n", "15 > RoE均值 >= 10\t250分\n", "10 > RoE均值 或 0 >= 其中一年\t0分" ], "id": "336aa970ee46709d" }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-13T03:10:23.578470Z", "start_time": "2025-01-13T03:10:03.791003Z" } }, "cell_type": "code", "source": [ "def cal_roe(df):\n", " df[\"prev_total_stockholder_interest\"] = df[\"total_stockholder_interest\"].shift(1)\n", " df[\"roe\"] = df[\"net_income\"] / ((df[\"prev_total_stockholder_interest\"] + df[\"total_stockholder_interest\"]) / 2)\n", " df.drop(columns=[\"prev_total_stockholder_interest\"], inplace=True)\n", "\n", "\n", "def score_by_roe(code):\n", " temp_df = finance_df[finance_df[\"code\"] == code].copy()\n", " cal_roe(temp_df)\n", "\n", " if any(roe < 0 for roe in temp_df[\"roe\"]):\n", " return 0\n", "\n", " average_roe = temp_df.nlargest(5, \"year\")[\"roe\"].mean() * 100\n", "\n", " if average_roe >= 35:\n", " return 550\n", " elif average_roe >= 30:\n", " return 500\n", " elif average_roe >= 25:\n", " return 450\n", " elif average_roe >= 15:\n", " return 300\n", " elif average_roe >= 10:\n", " return 250\n", " else:\n", " return 0\n", "\n", "\n", "codes = list(map(lambda x: add_score(x, score_by_roe(x[0])), codes))" ], "id": "f050d33c4a0cd720", "outputs": [], "execution_count": 187 }, { "metadata": {}, "cell_type": "markdown", "source": [ "总资产报酬率(%) RoA\t总资产报酬率RoA 能真实反映出一家公司的获利能力, 相当于一家公司的 「投资年化率」,当然越高越好。\n", "RoA均值 >= 15\t100分\n", "15 > RoA均值 >= 11\t80分\n", "11 > RoA均值 >= 7\t50分\n", "7 > RoA均值\t0分" ], "id": "6c2e1c602898e342" }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-13T03:10:42.654737Z", "start_time": "2025-01-13T03:10:23.580200Z" } }, "cell_type": "code", "source": [ "def cal_roa(df):\n", " df[\"prev_total_assets\"] = df[\"total_assets\"].shift(1)\n", " df[\"roa\"] = df[\"net_income\"] / ((df[\"prev_total_assets\"] + df[\"total_assets\"]) / 2)\n", " df.drop(columns=[\"prev_total_assets\"], inplace=True)\n", "\n", "\n", "def score_by_roa(code):\n", " temp_df = finance_df[finance_df[\"code\"] == code].copy()\n", " cal_roa(temp_df)\n", "\n", " average_roa = temp_df.nlargest(5, \"year\")[\"roa\"].mean() * 100\n", "\n", " if average_roa >= 15:\n", " return 100\n", " elif average_roa >= 11:\n", " return 80\n", " elif average_roa >= 7:\n", " return 50\n", " else:\n", " return 0\n", "\n", "\n", "codes = list(map(lambda x: add_score(x, score_by_roa(x[0])), codes))" ], "id": "25d1d5c0f7de460c", "outputs": [], "execution_count": 188 }, { "metadata": {}, "cell_type": "markdown", "source": [ "税后净利 规模(百万)\t获利规模大,那股价的”长期上涨潜力“也就会越稳健、越确定。选择时,大公司的优先级要高于小公司。\n", "税后净利均值 >= 10000\t150分\n", "10000 > 税后净利均值 >= 1000\t100分\n", "1000 > 税后净利均值\t0分" ], "id": "dbcb1d6b23582f3e" }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-13T03:10:58.085277Z", "start_time": "2025-01-13T03:10:42.657424Z" } }, "cell_type": "code", "source": [ "def score_by_net_income(code):\n", " temp_df = finance_df[finance_df[\"code\"] == code].copy()\n", " average_net_income = temp_df.nlargest(5, \"year\")[\"net_income\"].mean()\n", "\n", " if average_net_income >= 10000 * 10000000:\n", " return 150\n", " elif average_net_income >= 1000 * 10000000:\n", " return 100\n", " else:\n", " return 0\n", "\n", "\n", "codes = list(map(lambda x: add_score(x, score_by_net_income(x[0])), codes))" ], "id": "2f19c7fbb0afaa49", "outputs": [], "execution_count": 189 }, { "metadata": {}, "cell_type": "markdown", "source": [ "现金状况 分析\t总资产周转率 与 现金与约当现金占总资产的关系,可以看出公司的现金状况是否健康。\n", "规则①:总资产周转率 > 0.8 且 现金与约当现金占总资产(%) >= 10\t50分\n", "规则②:总资产周转率 < 0.8 且 现金与约当现金占总资产(%) >= 20\t50分\n", "不符合 规则① 或 规则②\t0分" ], "id": "2c6c934a376eef0d" }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-13T03:11:20.221255Z", "start_time": "2025-01-13T03:10:58.087417Z" } }, "cell_type": "code", "source": [ "def cal_total_assets_turnover_ratio(df):\n", " df[\"prev_total_assets\"] = df[\"total_assets\"].shift(1)\n", " df[\"total_assets_turnover_ratio\"] = df[\"total_revenue\"] / ((df[\"prev_total_assets\"] + df[\"total_assets\"]) / 2)\n", " df.drop(columns=[\"prev_total_assets\"], inplace=True)\n", "\n", "\n", "def cal_cash_ratio(df):\n", " df[\"cash_ratio\"] = df[\"cash\"] / df[\"total_assets\"]\n", "\n", "\n", "def score_by_assets_turnover_and_cash(code):\n", " temp_df = finance_df[finance_df[\"code\"] == code].copy()\n", "\n", " # 总资产周转率\n", " cal_total_assets_turnover_ratio(temp_df)\n", " total_assets_turnover_ratio = \\\n", " temp_df[temp_df[\"year\"] == temp_df[\"year\"].max()][\"total_assets_turnover_ratio\"].values[0] * 100\n", "\n", " # 现金比率\n", " cal_cash_ratio(temp_df)\n", " cash_ratio = temp_df[temp_df[\"year\"] == temp_df[\"year\"].max()][\"cash_ratio\"].values[0] * 100\n", "\n", " if total_assets_turnover_ratio > 80 and cash_ratio >= 10:\n", " return 50\n", " elif total_assets_turnover_ratio < 80 and cash_ratio >= 20:\n", " return 50\n", " else:\n", " return 0\n", "\n", "\n", "codes = list(map(lambda x: add_score(x, score_by_assets_turnover_and_cash(x[0])), codes))" ], "id": "31be2cb671b7adde", "outputs": [], "execution_count": 190 }, { "metadata": {}, "cell_type": "markdown", "source": [ "收现日数(日)\t平均收现日数越短,说明公司的经营能力越强。\n", "30 >= 平均收现日数\t20分\n", "平均收现日数 > 30\t0分\n", "\n", "销货日数(日)\t平均销货日数越短,说明公司商品越畅销。\n", "30 >= 平均销货日数\t20分\n", "平均销货日数 > 30\t0分\n", "\n", "收现日数+销货日数(日)\t生意周期 是否足够优秀,越短说明每年能做的生意趟数越多,经营能力就越强。\n", "40 >= 收现日数+销货日数\t20分\n", "60 >= 收现日数+销货日数 > 40\t10分\n", "平均销货日数 > 60\t0分" ], "id": "41ac526b0296b44b" }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-13T03:11:39.666059Z", "start_time": "2025-01-13T03:11:20.222910Z" } }, "cell_type": "code", "source": [ "# 收现日数\n", "def cal_collection_cash_period(df):\n", " df[\"collection_cash_period\"] = 360 / (df[\"total_revenue\"] / df[\"accounts_receivable\"])\n", "\n", "\n", "# 销货日数\n", "def cal_sales_period(df):\n", " df[\"sales_period\"] = 360 / (df[\"operating_costs\"] / df[\"inventories\"])\n", "\n", "\n", "def score_by_collection_cash_period_and_sales_period(code):\n", " temp_df = finance_df[finance_df[\"code\"] == code].copy()\n", "\n", " cal_collection_cash_period(temp_df)\n", " collection_cash_period = temp_df[temp_df[\"year\"] == temp_df[\"year\"].max()][\"collection_cash_period\"].values[0]\n", "\n", " cal_sales_period(temp_df)\n", " sales_period = temp_df[temp_df[\"year\"] == temp_df[\"year\"].max()][\"sales_period\"].values[0]\n", "\n", " score = 0\n", " if collection_cash_period < 30:\n", " score += 20\n", "\n", " if sales_period < 30:\n", " score += 20\n", "\n", " if (collection_cash_period + sales_period) < 40:\n", " score += 20\n", " elif (collection_cash_period + sales_period) < 60:\n", " score += 10\n", "\n", " return score\n", "\n", "\n", "codes = list(map(lambda x: add_score(x, score_by_collection_cash_period_and_sales_period(x[0])), codes))" ], "id": "ab6ff79c2650db7c", "outputs": [], "execution_count": 191 }, { "metadata": {}, "cell_type": "markdown", "source": [ "毛利率(%)\t毛利率 是否保持平稳,不大起大落。\n", "30% >= 毛利率平均波动幅度\t50分\n", "毛利率平均波动幅度 > 30%\t0分" ], "id": "a53bfdb799df8f48" }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-13T03:11:57.137395Z", "start_time": "2025-01-13T03:11:39.669792Z" } }, "cell_type": "code", "source": [ "# 毛利率\n", "def cal_gross_profit_ratio(df):\n", " df[\"gross_profit_ratio\"] = (df[\"total_revenue\"] - df[\"operating_costs\"]) / df[\"total_revenue\"]\n", "\n", "\n", "def score_by_gross_profit_ratio_volatility(code):\n", " temp_df = finance_df[finance_df[\"code\"] == code].copy()\n", " cal_gross_profit_ratio(temp_df)\n", " gross_profit_ratio_std = temp_df.nlargest(5, \"year\")[\"gross_profit_ratio\"].std() * 100\n", "\n", " if gross_profit_ratio_std < 30:\n", " return 50\n", " else:\n", " return 0\n", "\n", "\n", "codes = list(map(lambda x: add_score(x, score_by_gross_profit_ratio_volatility(x[0])), codes))" ], "id": "8e58e0114851ebcb", "outputs": [], "execution_count": 192 }, { "metadata": {}, "cell_type": "markdown", "source": [ "经营安全边际率(%)\t经营安全边际率越高,说明公司能够很好的控制成本,把大部分利润转化成实际收益, 获利能力很强,有利于抵御经济波动和价格竞争等影响。\n", "经营安全边际率 >= 70\t50分\n", "70 > 经营安全边际率 >= 50\t30分\n", "50 > 经营安全边际率 >= 30\t10分\n", "30 > 经营安全边际率\t0分" ], "id": "6613ab8263d4afef" }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-13T03:12:16.127651Z", "start_time": "2025-01-13T03:11:57.138994Z" } }, "cell_type": "code", "source": [ "# 经营安全边际\n", "def cal_operating_safety_margin(df):\n", " # 经营利润率\n", " df[\"operating_profit_ratio\"] = df[\"operating_profit\"] / df[\"total_revenue\"]\n", " df[\"operating_safety_margin\"] = df[\"operating_profit_ratio\"] / df[\"gross_profit_ratio\"]\n", "\n", "\n", "def score_by_operating_safety_margin(code):\n", " temp_df = finance_df[finance_df[\"code\"] == code].copy()\n", " cal_gross_profit_ratio(temp_df)\n", " cal_operating_safety_margin(temp_df)\n", "\n", " operating_safety_margin = temp_df[temp_df[\"year\"] == temp_df[\"year\"].max()][\"operating_safety_margin\"].values[0]\n", "\n", " if operating_safety_margin >= 70:\n", " return 50\n", " elif operating_safety_margin >= 50:\n", " return 30\n", " elif operating_safety_margin >= 30:\n", " return 10\n", " else:\n", " return 0\n", "\n", "\n", "codes = list(map(lambda x: add_score(x, score_by_operating_safety_margin(x[0])), codes))" ], "id": "d07048f574e163ab", "outputs": [], "execution_count": 193 }, { "metadata": {}, "cell_type": "markdown", "source": [ "税后净利\n", "年份由近(A)~远(E)\t公司赚的钱是否在逐年增长,是股价能长期上涨的基础。\n", "A年 > B年 (+) / A年 < B年 (-)\t+30分 / -30分\n", "B年 > C年 (+) / B年 < C年 (-)\t+25分 / -25分\n", "C年 > D年 (+) / C年 < D年 (-)\t+20分 / -20分\n", "D年 > E年 (+) / D年 < E年 (-)\t+15分 / -15分" ], "id": "2ee3712525455954" }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-13T03:12:31.905761Z", "start_time": "2025-01-13T03:12:16.129100Z" } }, "cell_type": "code", "source": [ "def score_by_net_income_ascending(code):\n", " temp_df = finance_df[finance_df[\"code\"] == code].copy()[[\"year\", \"net_income\"]]\n", " temp_df.sort_values(by=\"year\", ascending=False, inplace=True)\n", " temp_df.set_index(keys=\"year\", drop=True, inplace=True)\n", "\n", " score = 0\n", " if temp_df.iloc[0].values[0] > temp_df.iloc[1].values[0]:\n", " score += 30\n", " else:\n", " score -= 30\n", "\n", " if temp_df.iloc[1].values[0] > temp_df.iloc[2].values[0]:\n", " score += 25\n", " else:\n", " score -= 25\n", "\n", " if temp_df.iloc[2].values[0] > temp_df.iloc[3].values[0]:\n", " score += 20\n", " else:\n", " score -= 20\n", "\n", " if temp_df.iloc[3].values[0] > temp_df.iloc[4].values[0]:\n", " score += 15\n", " else:\n", " score -= 15\n", "\n", " return score\n", "\n", "\n", "codes = list(map(lambda x: add_score(x, score_by_net_income_ascending(x[0])), codes))" ], "id": "4ab6a7b485dc9349", "outputs": [], "execution_count": 194 }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-13T03:12:46.733835Z", "start_time": "2025-01-13T03:12:31.907382Z" } }, "cell_type": "code", "source": [ "def score_by_operating_net_cash_flow_ascending(code):\n", " temp_df = finance_df[finance_df[\"code\"] == code].copy()[[\"year\", \"operating_net_cash_flow\"]]\n", " temp_df.sort_values(by=\"year\", ascending=False, inplace=True)\n", " temp_df.set_index(keys=\"year\", drop=True, inplace=True)\n", "\n", " score = 0\n", " if temp_df.iloc[0].values[0] > temp_df.iloc[1].values[0]:\n", " score += 30\n", " else:\n", " score -= 30\n", "\n", " if temp_df.iloc[1].values[0] > temp_df.iloc[2].values[0]:\n", " score += 25\n", " else:\n", " score -= 25\n", "\n", " if temp_df.iloc[2].values[0] > temp_df.iloc[3].values[0]:\n", " score += 20\n", " else:\n", " score -= 20\n", "\n", " if temp_df.iloc[3].values[0] > temp_df.iloc[4].values[0]:\n", " score += 15\n", " else:\n", " score -= 15\n", "\n", " return score\n", "\n", "\n", "codes = list(map(lambda x: add_score(x, score_by_operating_net_cash_flow_ascending(x[0])), codes))" ], "id": "d6644089e803a79d", "outputs": [], "execution_count": 195 }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-13T03:12:46.753922Z", "start_time": "2025-01-13T03:12:46.734835Z" } }, "cell_type": "code", "source": [ "df = pd.DataFrame(codes,\n", " columns=[\"code\", \"name\", \"score\", \"roe_score\", \"roa_score\", \"net_income\", \"assets_turnover_and_cash\",\n", " \"collection_cash_period_and_sales_period\", \"gross_profit_ratio_volatility\",\n", " \"operating_safety_margin\", \"net_income_ascending\",\n", " \"operating_net_cash_flow_ascending\"])\n", "df.sort_values(by=\"score\", ascending=False, inplace=True)\n", "df" ], "id": "ef9e6259efc1c1d0", "outputs": [ { "data": { "text/plain": [ " code name score roe_score roa_score net_income \\\n", "2393 600519.SH 贵州茅台 950 500 100 100 \n", "323 000858.SZ 五粮液 910 450 100 100 \n", "144 000568.SZ 泸州老窖 850 450 100 0 \n", "3238 603688.SH 石英股份 850 500 100 0 \n", "2336 600438.SH 通威股份 840 450 80 100 \n", "... ... ... ... ... ... ... \n", "827 002425.SZ ST凯文 -100 0 0 0 \n", "1485 300200.SZ 高盟新材 -100 0 0 0 \n", "1619 300345.SZ 华民股份 -130 0 0 0 \n", "1488 300204.SZ 舒泰神 -130 0 0 0 \n", "1054 002672.SZ 东江环保 -130 0 0 0 \n", "\n", " assets_turnover_and_cash collection_cash_period_and_sales_period \\\n", "2393 50 20 \n", "323 50 20 \n", "144 50 20 \n", "3238 50 0 \n", "2336 50 50 \n", "... ... ... \n", "827 0 0 \n", "1485 0 0 \n", "1619 0 0 \n", "1488 0 0 \n", "1054 0 0 \n", "\n", " gross_profit_ratio_volatility operating_safety_margin \\\n", "2393 50 0 \n", "323 50 0 \n", "144 50 0 \n", "3238 50 0 \n", "2336 50 0 \n", "... ... ... \n", "827 50 0 \n", "1485 50 0 \n", "1619 50 0 \n", "1488 50 0 \n", "1054 50 0 \n", "\n", " net_income_ascending operating_net_cash_flow_ascending \n", "2393 90 40 \n", "323 90 50 \n", "144 90 90 \n", "3238 90 60 \n", "2336 30 30 \n", "... ... ... \n", "827 -90 -60 \n", "1485 -60 -90 \n", "1619 -90 -90 \n", "1488 -90 -90 \n", "1054 -90 -90 \n", "\n", "[3384 rows x 12 columns]" ], "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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
codenamescoreroe_scoreroa_scorenet_incomeassets_turnover_and_cashcollection_cash_period_and_sales_periodgross_profit_ratio_volatilityoperating_safety_marginnet_income_ascendingoperating_net_cash_flow_ascending
2393600519.SH贵州茅台95050010010050205009040
323000858.SZ五粮液91045010010050205009050
144000568.SZ泸州老窖850450100050205009090
3238603688.SH石英股份85050010005005009060
2336600438.SH通威股份8404508010050505003030
.......................................
827002425.SZST凯文-10000000500-90-60
1485300200.SZ高盟新材-10000000500-60-90
1619300345.SZ华民股份-13000000500-90-90
1488300204.SZ舒泰神-13000000500-90-90
1054002672.SZ东江环保-13000000500-90-90
\n", "

3384 rows × 12 columns

\n", "
" ] }, "execution_count": 196, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 196 }, { "metadata": { "ExecuteTime": { "end_time": "2025-01-13T03:17:08.882164Z", "start_time": "2025-01-13T03:17:08.862820Z" } }, "cell_type": "code", "source": [ "temp_df = finance_df[finance_df[\"code\"] == \"600763.SH\"]\n", "cal_roe(temp_df)\n", "cal_roa(temp_df)\n", "temp_df[[\"year\", \"roe\", \"roa\"]]" ], "id": "e6d973f4ff98ebef", "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/var/folders/7h/w0cmp4zj6mn9br_6nyj310m40000gn/T/ipykernel_51974/3287426981.py:2: SettingWithCopyWarning: \n", "A value is trying to be set on a copy of a slice from a DataFrame.\n", "Try using .loc[row_indexer,col_indexer] = value instead\n", "\n", "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n", " df[\"prev_total_stockholder_interest\"] = df[\"total_stockholder_interest\"].shift(1)\n", "/var/folders/7h/w0cmp4zj6mn9br_6nyj310m40000gn/T/ipykernel_51974/3287426981.py:3: SettingWithCopyWarning: \n", "A value is trying to be set on a copy of a slice from a DataFrame.\n", "Try using .loc[row_indexer,col_indexer] = value instead\n", "\n", "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n", " df[\"roe\"] = df[\"net_income\"] / ((df[\"prev_total_stockholder_interest\"] + df[\"total_stockholder_interest\"]) / 2)\n", "/var/folders/7h/w0cmp4zj6mn9br_6nyj310m40000gn/T/ipykernel_51974/3287426981.py:4: SettingWithCopyWarning: \n", "A value is trying to be set on a copy of a slice from a DataFrame\n", "\n", "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n", " df.drop(columns=[\"prev_total_stockholder_interest\"], inplace=True)\n", "/var/folders/7h/w0cmp4zj6mn9br_6nyj310m40000gn/T/ipykernel_51974/3105409447.py:2: SettingWithCopyWarning: \n", "A value is trying to be set on a copy of a slice from a DataFrame.\n", "Try using .loc[row_indexer,col_indexer] = value instead\n", "\n", "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n", " df[\"prev_total_assets\"] = df[\"total_assets\"].shift(1)\n", "/var/folders/7h/w0cmp4zj6mn9br_6nyj310m40000gn/T/ipykernel_51974/3105409447.py:3: SettingWithCopyWarning: \n", "A value is trying to be set on a copy of a slice from a DataFrame.\n", "Try using .loc[row_indexer,col_indexer] = value instead\n", "\n", "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n", " df[\"roa\"] = df[\"net_income\"] / ((df[\"prev_total_assets\"] + df[\"total_assets\"]) / 2)\n", "/var/folders/7h/w0cmp4zj6mn9br_6nyj310m40000gn/T/ipykernel_51974/3105409447.py:4: SettingWithCopyWarning: \n", "A value is trying to be set on a copy of a slice from a DataFrame\n", "\n", "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n", " df.drop(columns=[\"prev_total_assets\"], inplace=True)\n" ] }, { "data": { "text/plain": [ " year roe roa\n", "2979 2014 NaN NaN\n", "7615 2015 0.245119 0.182412\n", "12121 2016 0.148244 0.101560\n", "16405 2017 0.226923 0.147172\n", "21964 2018 0.282053 0.182929\n", "25657 2019 0.297166 0.211903\n", "29113 2020 0.252412 0.190406\n", "36313 2021 0.286244 0.196068\n", "40855 2022 0.182081 0.121805\n", "45977 2023 0.149449 0.103658" ], "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", "
yearroeroa
29792014NaNNaN
761520150.2451190.182412
1212120160.1482440.101560
1640520170.2269230.147172
2196420180.2820530.182929
2565720190.2971660.211903
2911320200.2524120.190406
3631320210.2862440.196068
4085520220.1820810.121805
4597720230.1494490.103658
\n", "
" ] }, "execution_count": 204, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 204 }, { "metadata": {}, "cell_type": "code", "outputs": [ { "data": { "text/plain": [ " ts_code end_date roe roa\n", "4 600763.SH 20231231 14.0666 13.4808\n", "10 600763.SH 20221231 17.7106 15.4075\n", "11 600763.SH 20221231 17.7106 15.4075\n", "18 600763.SH 20211231 27.9402 24.7367\n", "19 600763.SH 20211231 27.9402 24.7367\n", "26 600763.SH 20201231 25.0345 24.1350\n", "27 600763.SH 20201231 25.0345 24.1350\n", "34 600763.SH 20191231 29.8694 27.2723\n", "35 600763.SH 20191231 29.8694 27.2723\n", "42 600763.SH 20181231 28.7803 23.4500\n", "43 600763.SH 20181231 28.7803 23.4500\n", "50 600763.SH 20171231 23.9279 18.8885\n", "51 600763.SH 20171231 23.9279 18.8885\n", "58 600763.SH 20161231 16.6081 13.5829\n", "59 600763.SH 20161231 16.6081 13.5829\n", "66 600763.SH 20151231 26.5184 22.2861\n", "67 600763.SH 20151231 26.5184 22.2861\n", "74 600763.SH 20141231 19.1679 20.0538\n", "75 600763.SH 20141231 19.1679 20.0538" ], "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", " \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", "
ts_codeend_dateroeroa
4600763.SH2023123114.066613.4808
10600763.SH2022123117.710615.4075
11600763.SH2022123117.710615.4075
18600763.SH2021123127.940224.7367
19600763.SH2021123127.940224.7367
26600763.SH2020123125.034524.1350
27600763.SH2020123125.034524.1350
34600763.SH2019123129.869427.2723
35600763.SH2019123129.869427.2723
42600763.SH2018123128.780323.4500
43600763.SH2018123128.780323.4500
50600763.SH2017123123.927918.8885
51600763.SH2017123123.927918.8885
58600763.SH2016123116.608113.5829
59600763.SH2016123116.608113.5829
66600763.SH2015123126.518422.2861
67600763.SH2015123126.518422.2861
74600763.SH2014123119.167920.0538
75600763.SH2014123119.167920.0538
\n", "
" ] }, "execution_count": 206, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 206, "source": [ "temp_df = ts_pro.fina_indicator(ts_code=\"600763.SH\", start_date=\"20140101\", end_date=\"20241231\",\n", " fields=\"ts_code,end_date,roe,roa\")\n", "temp_df = temp_df[temp_df[\"end_date\"].str.endswith(\"1231\")]\n", "# temp_df[\"end_date\"] = temp_df[\"end_date\"].str[:4]\n", "# temp_df = temp_df.drop_duplicates(subset=[\"end_date\"], keep=\"last\")\n", "temp_df" ], "id": "b220252765677c76" } ], "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 }