1479 lines
49 KiB
Plaintext
1479 lines
49 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "code",
|
||
"id": "initial_id",
|
||
"metadata": {
|
||
"collapsed": true,
|
||
"ExecuteTime": {
|
||
"end_time": "2025-01-14T14:10:53.801418Z",
|
||
"start_time": "2025-01-14T14:10:53.532671Z"
|
||
}
|
||
},
|
||
"source": [
|
||
"import pandas as pd\n",
|
||
"import tushare as ts\n",
|
||
"\n",
|
||
"ts_pro = ts.pro_api(token=\"64ebff4fa679167600b905ee45dd88e76f3963c0ff39157f3f085f0e\")"
|
||
],
|
||
"outputs": [],
|
||
"execution_count": 2
|
||
},
|
||
{
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2025-01-14T14:10:56.411909Z",
|
||
"start_time": "2025-01-14T14:10:55.020264Z"
|
||
}
|
||
},
|
||
"cell_type": "code",
|
||
"source": [
|
||
"import loader as loader\n",
|
||
"\n",
|
||
"# 加载股票信息\n",
|
||
"stock_df = pd.read_csv(\"../材料/股票基础信息.csv\")\n",
|
||
"# 加载财报信息\n",
|
||
"source_finance_df = loader.load_finance()\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": 3
|
||
},
|
||
{
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2025-01-14T14:22:17.070395Z",
|
||
"start_time": "2025-01-14T14:22:17.053180Z"
|
||
}
|
||
},
|
||
"cell_type": "code",
|
||
"source": "finance_df[finance_df[\"code\"] == \"600763.SH\"][[\"year\", \"net_income\"]]",
|
||
"id": "f0e8942b3403348c",
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
" year net_income\n",
|
||
"1808 2005 3.467468e+06\n",
|
||
"3228 2006 1.212677e+06\n",
|
||
"4784 2007 1.015147e+07\n",
|
||
"8425 2008 1.466373e+07\n",
|
||
"9811 2009 2.172666e+07\n",
|
||
"12426 2010 4.982651e+07\n",
|
||
"17669 2011 7.169039e+07\n",
|
||
"19876 2012 9.554584e+07\n",
|
||
"25082 2013 1.024329e+08\n",
|
||
"28480 2014 1.138340e+08\n",
|
||
"33116 2015 1.936414e+08\n",
|
||
"37622 2016 1.328421e+08\n",
|
||
"41906 2017 2.266875e+08\n",
|
||
"47465 2018 3.592014e+08\n",
|
||
"51158 2019 5.077704e+08\n",
|
||
"54614 2020 5.449616e+08\n",
|
||
"61814 2021 7.861501e+08\n",
|
||
"66356 2022 6.156781e+08\n",
|
||
"71478 2023 5.784234e+08"
|
||
],
|
||
"text/html": [
|
||
"<div>\n",
|
||
"<style scoped>\n",
|
||
" .dataframe tbody tr th:only-of-type {\n",
|
||
" vertical-align: middle;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe tbody tr th {\n",
|
||
" vertical-align: top;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe thead th {\n",
|
||
" text-align: right;\n",
|
||
" }\n",
|
||
"</style>\n",
|
||
"<table border=\"1\" class=\"dataframe\">\n",
|
||
" <thead>\n",
|
||
" <tr style=\"text-align: right;\">\n",
|
||
" <th></th>\n",
|
||
" <th>year</th>\n",
|
||
" <th>net_income</th>\n",
|
||
" </tr>\n",
|
||
" </thead>\n",
|
||
" <tbody>\n",
|
||
" <tr>\n",
|
||
" <th>1808</th>\n",
|
||
" <td>2005</td>\n",
|
||
" <td>3.467468e+06</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>3228</th>\n",
|
||
" <td>2006</td>\n",
|
||
" <td>1.212677e+06</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>4784</th>\n",
|
||
" <td>2007</td>\n",
|
||
" <td>1.015147e+07</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>8425</th>\n",
|
||
" <td>2008</td>\n",
|
||
" <td>1.466373e+07</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>9811</th>\n",
|
||
" <td>2009</td>\n",
|
||
" <td>2.172666e+07</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>12426</th>\n",
|
||
" <td>2010</td>\n",
|
||
" <td>4.982651e+07</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>17669</th>\n",
|
||
" <td>2011</td>\n",
|
||
" <td>7.169039e+07</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>19876</th>\n",
|
||
" <td>2012</td>\n",
|
||
" <td>9.554584e+07</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>25082</th>\n",
|
||
" <td>2013</td>\n",
|
||
" <td>1.024329e+08</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>28480</th>\n",
|
||
" <td>2014</td>\n",
|
||
" <td>1.138340e+08</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>33116</th>\n",
|
||
" <td>2015</td>\n",
|
||
" <td>1.936414e+08</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>37622</th>\n",
|
||
" <td>2016</td>\n",
|
||
" <td>1.328421e+08</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>41906</th>\n",
|
||
" <td>2017</td>\n",
|
||
" <td>2.266875e+08</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>47465</th>\n",
|
||
" <td>2018</td>\n",
|
||
" <td>3.592014e+08</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>51158</th>\n",
|
||
" <td>2019</td>\n",
|
||
" <td>5.077704e+08</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>54614</th>\n",
|
||
" <td>2020</td>\n",
|
||
" <td>5.449616e+08</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>61814</th>\n",
|
||
" <td>2021</td>\n",
|
||
" <td>7.861501e+08</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>66356</th>\n",
|
||
" <td>2022</td>\n",
|
||
" <td>6.156781e+08</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>71478</th>\n",
|
||
" <td>2023</td>\n",
|
||
" <td>5.784234e+08</td>\n",
|
||
" </tr>\n",
|
||
" </tbody>\n",
|
||
"</table>\n",
|
||
"</div>"
|
||
]
|
||
},
|
||
"execution_count": 4,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"execution_count": 4
|
||
},
|
||
{
|
||
"metadata": {},
|
||
"cell_type": "markdown",
|
||
"source": "过滤上市时间大于5年的企业,由于计算很多数值需要与前一年比,所以实际上需要的是上市时间至少6年的企业",
|
||
"id": "3052b8c4442f3643"
|
||
},
|
||
{
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2025-01-14T14:22:57.782337Z",
|
||
"start_time": "2025-01-14T14:22:57.774714Z"
|
||
}
|
||
},
|
||
"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": 5
|
||
},
|
||
{
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2025-01-14T14:22:59.917536Z",
|
||
"start_time": "2025-01-14T14:22:59.914056Z"
|
||
}
|
||
},
|
||
"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": 6
|
||
},
|
||
{
|
||
"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-14T14:23:11.032339Z",
|
||
"start_time": "2025-01-14T14:23:02.481495Z"
|
||
}
|
||
},
|
||
"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": 7
|
||
},
|
||
{
|
||
"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-14T14:23:20.494927Z",
|
||
"start_time": "2025-01-14T14:23:12.064079Z"
|
||
}
|
||
},
|
||
"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": 8
|
||
},
|
||
{
|
||
"metadata": {},
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"税后净利 规模(百万)\t获利规模大,那股价的”长期上涨潜力“也就会越稳健、越确定。选择时,大公司的优先级要高于小公司。\n",
|
||
"税后净利均值 >= 10000\t150分\n",
|
||
"10000 > 税后净利均值 >= 1000\t100分\n",
|
||
"1000 > 税后净利均值\t0分"
|
||
],
|
||
"id": "dbcb1d6b23582f3e"
|
||
},
|
||
{
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2025-01-14T14:23:29.214393Z",
|
||
"start_time": "2025-01-14T14:23:22.256675Z"
|
||
}
|
||
},
|
||
"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": 9
|
||
},
|
||
{
|
||
"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-14T14:23:39.246944Z",
|
||
"start_time": "2025-01-14T14:23:30.739476Z"
|
||
}
|
||
},
|
||
"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": 10
|
||
},
|
||
{
|
||
"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-14T14:23:47.733800Z",
|
||
"start_time": "2025-01-14T14:23:40.102117Z"
|
||
}
|
||
},
|
||
"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": 11
|
||
},
|
||
{
|
||
"metadata": {},
|
||
"cell_type": "markdown",
|
||
"source": [
|
||
"毛利率(%)\t毛利率 是否保持平稳,不大起大落。\n",
|
||
"30% >= 毛利率平均波动幅度\t50分\n",
|
||
"毛利率平均波动幅度 > 30%\t0分"
|
||
],
|
||
"id": "a53bfdb799df8f48"
|
||
},
|
||
{
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2025-01-14T14:23:57.280972Z",
|
||
"start_time": "2025-01-14T14:23:49.457909Z"
|
||
}
|
||
},
|
||
"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": 12
|
||
},
|
||
{
|
||
"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-14T14:24:05.675449Z",
|
||
"start_time": "2025-01-14T14:23:58.156821Z"
|
||
}
|
||
},
|
||
"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": 13
|
||
},
|
||
{
|
||
"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-14T14:24:13.783225Z",
|
||
"start_time": "2025-01-14T14:24:06.605156Z"
|
||
}
|
||
},
|
||
"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": 14
|
||
},
|
||
{
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2025-01-14T14:24:21.962980Z",
|
||
"start_time": "2025-01-14T14:24:14.785970Z"
|
||
}
|
||
},
|
||
"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": 15
|
||
},
|
||
{
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2025-01-14T14:24:24.969522Z",
|
||
"start_time": "2025-01-14T14:24:24.957769Z"
|
||
}
|
||
},
|
||
"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",
|
||
"3238 603688.SH 石英股份 850 500 100 0 \n",
|
||
"144 000568.SZ 泸州老窖 850 450 100 0 \n",
|
||
"2336 600438.SH 通威股份 840 450 80 100 \n",
|
||
"... ... ... ... ... ... ... \n",
|
||
"1703 300436.SZ 广生堂 -100 0 0 0 \n",
|
||
"2441 600579.SH 克劳斯 -100 0 0 0 \n",
|
||
"1054 002672.SZ 东江环保 -130 0 0 0 \n",
|
||
"1488 300204.SZ 舒泰神 -130 0 0 0 \n",
|
||
"1619 300345.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",
|
||
"3238 50 0 \n",
|
||
"144 50 20 \n",
|
||
"2336 50 50 \n",
|
||
"... ... ... \n",
|
||
"1703 0 0 \n",
|
||
"2441 0 0 \n",
|
||
"1054 0 0 \n",
|
||
"1488 0 0 \n",
|
||
"1619 0 0 \n",
|
||
"\n",
|
||
" gross_profit_ratio_volatility operating_safety_margin \\\n",
|
||
"2393 50 0 \n",
|
||
"323 50 0 \n",
|
||
"3238 50 0 \n",
|
||
"144 50 0 \n",
|
||
"2336 50 0 \n",
|
||
"... ... ... \n",
|
||
"1703 50 0 \n",
|
||
"2441 50 0 \n",
|
||
"1054 50 0 \n",
|
||
"1488 50 0 \n",
|
||
"1619 50 0 \n",
|
||
"\n",
|
||
" net_income_ascending operating_net_cash_flow_ascending \n",
|
||
"2393 90 40 \n",
|
||
"323 90 50 \n",
|
||
"3238 90 60 \n",
|
||
"144 90 90 \n",
|
||
"2336 30 30 \n",
|
||
"... ... ... \n",
|
||
"1703 -60 -90 \n",
|
||
"2441 -90 -60 \n",
|
||
"1054 -90 -90 \n",
|
||
"1488 -90 -90 \n",
|
||
"1619 -90 -90 \n",
|
||
"\n",
|
||
"[3384 rows x 12 columns]"
|
||
],
|
||
"text/html": [
|
||
"<div>\n",
|
||
"<style scoped>\n",
|
||
" .dataframe tbody tr th:only-of-type {\n",
|
||
" vertical-align: middle;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe tbody tr th {\n",
|
||
" vertical-align: top;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe thead th {\n",
|
||
" text-align: right;\n",
|
||
" }\n",
|
||
"</style>\n",
|
||
"<table border=\"1\" class=\"dataframe\">\n",
|
||
" <thead>\n",
|
||
" <tr style=\"text-align: right;\">\n",
|
||
" <th></th>\n",
|
||
" <th>code</th>\n",
|
||
" <th>name</th>\n",
|
||
" <th>score</th>\n",
|
||
" <th>roe_score</th>\n",
|
||
" <th>roa_score</th>\n",
|
||
" <th>net_income</th>\n",
|
||
" <th>assets_turnover_and_cash</th>\n",
|
||
" <th>collection_cash_period_and_sales_period</th>\n",
|
||
" <th>gross_profit_ratio_volatility</th>\n",
|
||
" <th>operating_safety_margin</th>\n",
|
||
" <th>net_income_ascending</th>\n",
|
||
" <th>operating_net_cash_flow_ascending</th>\n",
|
||
" </tr>\n",
|
||
" </thead>\n",
|
||
" <tbody>\n",
|
||
" <tr>\n",
|
||
" <th>2393</th>\n",
|
||
" <td>600519.SH</td>\n",
|
||
" <td>贵州茅台</td>\n",
|
||
" <td>950</td>\n",
|
||
" <td>500</td>\n",
|
||
" <td>100</td>\n",
|
||
" <td>100</td>\n",
|
||
" <td>50</td>\n",
|
||
" <td>20</td>\n",
|
||
" <td>50</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>90</td>\n",
|
||
" <td>40</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>323</th>\n",
|
||
" <td>000858.SZ</td>\n",
|
||
" <td>五粮液</td>\n",
|
||
" <td>910</td>\n",
|
||
" <td>450</td>\n",
|
||
" <td>100</td>\n",
|
||
" <td>100</td>\n",
|
||
" <td>50</td>\n",
|
||
" <td>20</td>\n",
|
||
" <td>50</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>90</td>\n",
|
||
" <td>50</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>3238</th>\n",
|
||
" <td>603688.SH</td>\n",
|
||
" <td>石英股份</td>\n",
|
||
" <td>850</td>\n",
|
||
" <td>500</td>\n",
|
||
" <td>100</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>50</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>50</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>90</td>\n",
|
||
" <td>60</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>144</th>\n",
|
||
" <td>000568.SZ</td>\n",
|
||
" <td>泸州老窖</td>\n",
|
||
" <td>850</td>\n",
|
||
" <td>450</td>\n",
|
||
" <td>100</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>50</td>\n",
|
||
" <td>20</td>\n",
|
||
" <td>50</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>90</td>\n",
|
||
" <td>90</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>2336</th>\n",
|
||
" <td>600438.SH</td>\n",
|
||
" <td>通威股份</td>\n",
|
||
" <td>840</td>\n",
|
||
" <td>450</td>\n",
|
||
" <td>80</td>\n",
|
||
" <td>100</td>\n",
|
||
" <td>50</td>\n",
|
||
" <td>50</td>\n",
|
||
" <td>50</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>30</td>\n",
|
||
" <td>30</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>...</th>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" <td>...</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>1703</th>\n",
|
||
" <td>300436.SZ</td>\n",
|
||
" <td>广生堂</td>\n",
|
||
" <td>-100</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>50</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>-60</td>\n",
|
||
" <td>-90</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>2441</th>\n",
|
||
" <td>600579.SH</td>\n",
|
||
" <td>克劳斯</td>\n",
|
||
" <td>-100</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>50</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>-90</td>\n",
|
||
" <td>-60</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>1054</th>\n",
|
||
" <td>002672.SZ</td>\n",
|
||
" <td>东江环保</td>\n",
|
||
" <td>-130</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>50</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>-90</td>\n",
|
||
" <td>-90</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>1488</th>\n",
|
||
" <td>300204.SZ</td>\n",
|
||
" <td>舒泰神</td>\n",
|
||
" <td>-130</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>50</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>-90</td>\n",
|
||
" <td>-90</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>1619</th>\n",
|
||
" <td>300345.SZ</td>\n",
|
||
" <td>华民股份</td>\n",
|
||
" <td>-130</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>50</td>\n",
|
||
" <td>0</td>\n",
|
||
" <td>-90</td>\n",
|
||
" <td>-90</td>\n",
|
||
" </tr>\n",
|
||
" </tbody>\n",
|
||
"</table>\n",
|
||
"<p>3384 rows × 12 columns</p>\n",
|
||
"</div>"
|
||
]
|
||
},
|
||
"execution_count": 16,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"execution_count": 16
|
||
},
|
||
{
|
||
"metadata": {
|
||
"ExecuteTime": {
|
||
"end_time": "2025-01-14T14:25:22.482926Z",
|
||
"start_time": "2025-01-14T14:25:22.476830Z"
|
||
}
|
||
},
|
||
"cell_type": "code",
|
||
"source": "df[:100][\"code\"]",
|
||
"id": "32b5b4778985afaa",
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"2393 600519.SH\n",
|
||
"323 000858.SZ\n",
|
||
"3238 603688.SH\n",
|
||
"144 000568.SZ\n",
|
||
"2336 600438.SH\n",
|
||
" ... \n",
|
||
"3318 603871.SH\n",
|
||
"2542 600702.SH\n",
|
||
"1166 002801.SZ\n",
|
||
"1227 002867.SZ\n",
|
||
"1754 300487.SZ\n",
|
||
"Name: code, Length: 100, dtype: object"
|
||
]
|
||
},
|
||
"execution_count": 17,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"execution_count": 17
|
||
},
|
||
{
|
||
"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": [
|
||
"<div>\n",
|
||
"<style scoped>\n",
|
||
" .dataframe tbody tr th:only-of-type {\n",
|
||
" vertical-align: middle;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe tbody tr th {\n",
|
||
" vertical-align: top;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe thead th {\n",
|
||
" text-align: right;\n",
|
||
" }\n",
|
||
"</style>\n",
|
||
"<table border=\"1\" class=\"dataframe\">\n",
|
||
" <thead>\n",
|
||
" <tr style=\"text-align: right;\">\n",
|
||
" <th></th>\n",
|
||
" <th>year</th>\n",
|
||
" <th>roe</th>\n",
|
||
" <th>roa</th>\n",
|
||
" </tr>\n",
|
||
" </thead>\n",
|
||
" <tbody>\n",
|
||
" <tr>\n",
|
||
" <th>2979</th>\n",
|
||
" <td>2014</td>\n",
|
||
" <td>NaN</td>\n",
|
||
" <td>NaN</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>7615</th>\n",
|
||
" <td>2015</td>\n",
|
||
" <td>0.245119</td>\n",
|
||
" <td>0.182412</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>12121</th>\n",
|
||
" <td>2016</td>\n",
|
||
" <td>0.148244</td>\n",
|
||
" <td>0.101560</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>16405</th>\n",
|
||
" <td>2017</td>\n",
|
||
" <td>0.226923</td>\n",
|
||
" <td>0.147172</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>21964</th>\n",
|
||
" <td>2018</td>\n",
|
||
" <td>0.282053</td>\n",
|
||
" <td>0.182929</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>25657</th>\n",
|
||
" <td>2019</td>\n",
|
||
" <td>0.297166</td>\n",
|
||
" <td>0.211903</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>29113</th>\n",
|
||
" <td>2020</td>\n",
|
||
" <td>0.252412</td>\n",
|
||
" <td>0.190406</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>36313</th>\n",
|
||
" <td>2021</td>\n",
|
||
" <td>0.286244</td>\n",
|
||
" <td>0.196068</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>40855</th>\n",
|
||
" <td>2022</td>\n",
|
||
" <td>0.182081</td>\n",
|
||
" <td>0.121805</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>45977</th>\n",
|
||
" <td>2023</td>\n",
|
||
" <td>0.149449</td>\n",
|
||
" <td>0.103658</td>\n",
|
||
" </tr>\n",
|
||
" </tbody>\n",
|
||
"</table>\n",
|
||
"</div>"
|
||
]
|
||
},
|
||
"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": [
|
||
"<div>\n",
|
||
"<style scoped>\n",
|
||
" .dataframe tbody tr th:only-of-type {\n",
|
||
" vertical-align: middle;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe tbody tr th {\n",
|
||
" vertical-align: top;\n",
|
||
" }\n",
|
||
"\n",
|
||
" .dataframe thead th {\n",
|
||
" text-align: right;\n",
|
||
" }\n",
|
||
"</style>\n",
|
||
"<table border=\"1\" class=\"dataframe\">\n",
|
||
" <thead>\n",
|
||
" <tr style=\"text-align: right;\">\n",
|
||
" <th></th>\n",
|
||
" <th>ts_code</th>\n",
|
||
" <th>end_date</th>\n",
|
||
" <th>roe</th>\n",
|
||
" <th>roa</th>\n",
|
||
" </tr>\n",
|
||
" </thead>\n",
|
||
" <tbody>\n",
|
||
" <tr>\n",
|
||
" <th>4</th>\n",
|
||
" <td>600763.SH</td>\n",
|
||
" <td>20231231</td>\n",
|
||
" <td>14.0666</td>\n",
|
||
" <td>13.4808</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>10</th>\n",
|
||
" <td>600763.SH</td>\n",
|
||
" <td>20221231</td>\n",
|
||
" <td>17.7106</td>\n",
|
||
" <td>15.4075</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>11</th>\n",
|
||
" <td>600763.SH</td>\n",
|
||
" <td>20221231</td>\n",
|
||
" <td>17.7106</td>\n",
|
||
" <td>15.4075</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>18</th>\n",
|
||
" <td>600763.SH</td>\n",
|
||
" <td>20211231</td>\n",
|
||
" <td>27.9402</td>\n",
|
||
" <td>24.7367</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>19</th>\n",
|
||
" <td>600763.SH</td>\n",
|
||
" <td>20211231</td>\n",
|
||
" <td>27.9402</td>\n",
|
||
" <td>24.7367</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>26</th>\n",
|
||
" <td>600763.SH</td>\n",
|
||
" <td>20201231</td>\n",
|
||
" <td>25.0345</td>\n",
|
||
" <td>24.1350</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>27</th>\n",
|
||
" <td>600763.SH</td>\n",
|
||
" <td>20201231</td>\n",
|
||
" <td>25.0345</td>\n",
|
||
" <td>24.1350</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>34</th>\n",
|
||
" <td>600763.SH</td>\n",
|
||
" <td>20191231</td>\n",
|
||
" <td>29.8694</td>\n",
|
||
" <td>27.2723</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>35</th>\n",
|
||
" <td>600763.SH</td>\n",
|
||
" <td>20191231</td>\n",
|
||
" <td>29.8694</td>\n",
|
||
" <td>27.2723</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>42</th>\n",
|
||
" <td>600763.SH</td>\n",
|
||
" <td>20181231</td>\n",
|
||
" <td>28.7803</td>\n",
|
||
" <td>23.4500</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>43</th>\n",
|
||
" <td>600763.SH</td>\n",
|
||
" <td>20181231</td>\n",
|
||
" <td>28.7803</td>\n",
|
||
" <td>23.4500</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>50</th>\n",
|
||
" <td>600763.SH</td>\n",
|
||
" <td>20171231</td>\n",
|
||
" <td>23.9279</td>\n",
|
||
" <td>18.8885</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>51</th>\n",
|
||
" <td>600763.SH</td>\n",
|
||
" <td>20171231</td>\n",
|
||
" <td>23.9279</td>\n",
|
||
" <td>18.8885</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>58</th>\n",
|
||
" <td>600763.SH</td>\n",
|
||
" <td>20161231</td>\n",
|
||
" <td>16.6081</td>\n",
|
||
" <td>13.5829</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>59</th>\n",
|
||
" <td>600763.SH</td>\n",
|
||
" <td>20161231</td>\n",
|
||
" <td>16.6081</td>\n",
|
||
" <td>13.5829</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>66</th>\n",
|
||
" <td>600763.SH</td>\n",
|
||
" <td>20151231</td>\n",
|
||
" <td>26.5184</td>\n",
|
||
" <td>22.2861</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>67</th>\n",
|
||
" <td>600763.SH</td>\n",
|
||
" <td>20151231</td>\n",
|
||
" <td>26.5184</td>\n",
|
||
" <td>22.2861</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>74</th>\n",
|
||
" <td>600763.SH</td>\n",
|
||
" <td>20141231</td>\n",
|
||
" <td>19.1679</td>\n",
|
||
" <td>20.0538</td>\n",
|
||
" </tr>\n",
|
||
" <tr>\n",
|
||
" <th>75</th>\n",
|
||
" <td>600763.SH</td>\n",
|
||
" <td>20141231</td>\n",
|
||
" <td>19.1679</td>\n",
|
||
" <td>20.0538</td>\n",
|
||
" </tr>\n",
|
||
" </tbody>\n",
|
||
"</table>\n",
|
||
"</div>"
|
||
]
|
||
},
|
||
"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
|
||
}
|