1
0

Compare commits

...

19 Commits

Author SHA1 Message Date
1ae75a3e6c 增加数据采集 2025-09-17 18:35:03 +08:00
d4a5a8f586 设计止损函数 2025-02-23 22:18:37 +08:00
5dcc00d9b2 修正MACD策略参数 2025-02-21 11:56:28 +08:00
edec606449 增加批量回测函数 2025-02-19 23:18:19 +08:00
2b01c56471 修正策略的编写 2025-02-19 18:43:14 +08:00
b8f97f7203 新增backtesting框架用于回测 2025-02-18 18:01:01 +08:00
5489a0bb4b 完成macd回测 2025-02-17 22:35:46 +08:00
3f8b210564 尝试在策略内部使用talib计算指标 2025-02-17 18:28:08 +08:00
9689625fc1 完成macd回测 2025-02-16 23:24:34 +08:00
46a539cf72 尝试构建回测模块 2025-02-13 18:21:54 +08:00
e1eba0559e 学习使用backtrader 2025-02-11 22:56:21 +08:00
5236a0f6f9 尝试构建回测模块 2025-02-11 17:35:00 +08:00
e856588b6e 进行了一些尝试 2025-02-10 23:22:55 +08:00
7092fd65c4 优化代码 2025-02-10 17:28:30 +08:00
32f563518d 进行了一番计算 2025-01-22 16:03:28 +08:00
2901905e20 更新依赖信息 2025-01-22 09:00:45 +08:00
f34ce1374b K线分析 2025-01-21 23:19:07 +08:00
576d9abc3c 完成金字塔选股 2025-01-20 18:14:42 +08:00
bdacbcde9d 完善金字塔选股策略计算 2025-01-20 17:16:34 +08:00
11 changed files with 14814 additions and 1959 deletions

10
note.md Normal file
View File

@@ -0,0 +1,10 @@
talib安装
macOS
```
poetry run pip install TA-Lib
```
Windows
> https://github.com/cgohlke/talib-build
```
poetry run pip install ta_lib-0.6.3-cp312-cp312-win_amd64.whl
```

3816
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -14,6 +14,9 @@ jupyter = "^1.1.1"
matplotlib = "^3.10.0"
prophet = "^1.1.6"
mplfinance = "^0.12.10b0"
scipy = "^1.15.1"
backtrader = "^1.9.78.123"
backtesting = "^0.6.1"
[build-system]

3456
回测/backtesting.ipynb Normal file

File diff suppressed because one or more lines are too long

403
回测/backtrader.ipynb Normal file

File diff suppressed because one or more lines are too long

587
材料准备/ta-lib.ipynb Normal file
View File

@@ -0,0 +1,587 @@
{
"cells": [
{
"cell_type": "code",
"id": "initial_id",
"metadata": {
"collapsed": true,
"ExecuteTime": {
"end_time": "2025-02-11T06:31:19.433336Z",
"start_time": "2025-02-11T06:31:18.884130Z"
}
},
"source": [
"import pandas as pd\n",
"\n",
"# source_df = \\\n",
"# pd.read_csv(\"C:\\\\Users\\\\lanyuanxiaoyao\\\\SynologyDrive\\\\data\\\\Tushare\\\\日线行情 1990-2024\\\\分组行情\\\\000001.SZ.csv\") \\\n",
"source_df = pd.read_csv(\"/Users/lanyuanxiaoyao/SynologyDrive/data/Tushare/日线行情 1990-2024/分组行情/600519.SH.csv\") \\\n",
" [[\"trade_date\", \"vol\", \"open_qfq\", \"close_qfq\", \"high_qfq\", \"low_qfq\", \"macd\", \"macd_dif\", \"macd_dea\"]]\n",
"df = pd.DataFrame()\n",
"df[[\"date\", \"volume\", \"open\", \"close\", \"high\", \"low\", \"macd\", \"macd_dif\", \"macd_dea\"]] = \\\n",
" source_df[[\"trade_date\", \"vol\", \"open_qfq\", \"close_qfq\", \"high_qfq\", \"low_qfq\", \"macd\", \"macd_dif\", \"macd_dea\"]]\n",
"df[\"datetime\"] = pd.to_datetime(df[\"date\"], format=\"%Y%m%d\")\n",
"df[\"datetime_text\"] = df[\"datetime\"].apply(lambda x: x.strftime(\"%Y%m%d\"))\n",
"df.sort_values(by='datetime', inplace=True)\n",
"df"
],
"outputs": [
{
"data": {
"text/plain": [
" date volume open close high low \\\n",
"2187 20010827 406318.00 4.23675 4.36443 4.63820 4.03295 \n",
"2188 20010828 129647.79 4.29568 4.52525 4.54244 4.24902 \n",
"2189 20010829 53252.75 4.53999 4.46632 4.54244 4.43195 \n",
"2190 20010830 48013.06 4.45405 4.55472 4.60505 4.41967 \n",
"2191 20010831 23231.48 4.56086 4.54367 4.61856 4.51789 \n",
"... ... ... ... ... ... ... \n",
"2182 20241225 17123.39 1538.80000 1530.00000 1538.80000 1526.10000 \n",
"2183 20241226 18286.51 1534.00000 1527.79000 1538.78000 1523.00000 \n",
"2184 20241227 20759.32 1528.90000 1528.97000 1536.00000 1519.50000 \n",
"2185 20241230 25129.82 1533.97000 1525.00000 1543.96000 1525.00000 \n",
"2186 20241231 39354.45 1525.40000 1524.00000 1545.00000 1522.01000 \n",
"\n",
" macd macd_dif macd_dea datetime datetime_text \n",
"2187 0.000 0.000 0.000 2001-08-27 20010827 \n",
"2188 0.021 0.013 0.003 2001-08-28 20010828 \n",
"2189 0.025 0.018 0.006 2001-08-29 20010829 \n",
"2190 0.037 0.029 0.010 2001-08-30 20010830 \n",
"2191 0.042 0.036 0.016 2001-08-31 20010831 \n",
"... ... ... ... ... ... \n",
"2182 5.430 5.063 2.348 2024-12-25 20241225 \n",
"2183 4.192 4.968 2.872 2024-12-26 20241226 \n",
"2184 3.295 4.931 3.283 2024-12-27 20241227 \n",
"2185 1.993 4.529 3.533 2024-12-30 20241230 \n",
"2186 0.880 4.083 3.643 2024-12-31 20241231 \n",
"\n",
"[5591 rows x 11 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>date</th>\n",
" <th>volume</th>\n",
" <th>open</th>\n",
" <th>close</th>\n",
" <th>high</th>\n",
" <th>low</th>\n",
" <th>macd</th>\n",
" <th>macd_dif</th>\n",
" <th>macd_dea</th>\n",
" <th>datetime</th>\n",
" <th>datetime_text</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>2187</th>\n",
" <td>20010827</td>\n",
" <td>406318.00</td>\n",
" <td>4.23675</td>\n",
" <td>4.36443</td>\n",
" <td>4.63820</td>\n",
" <td>4.03295</td>\n",
" <td>0.000</td>\n",
" <td>0.000</td>\n",
" <td>0.000</td>\n",
" <td>2001-08-27</td>\n",
" <td>20010827</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2188</th>\n",
" <td>20010828</td>\n",
" <td>129647.79</td>\n",
" <td>4.29568</td>\n",
" <td>4.52525</td>\n",
" <td>4.54244</td>\n",
" <td>4.24902</td>\n",
" <td>0.021</td>\n",
" <td>0.013</td>\n",
" <td>0.003</td>\n",
" <td>2001-08-28</td>\n",
" <td>20010828</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2189</th>\n",
" <td>20010829</td>\n",
" <td>53252.75</td>\n",
" <td>4.53999</td>\n",
" <td>4.46632</td>\n",
" <td>4.54244</td>\n",
" <td>4.43195</td>\n",
" <td>0.025</td>\n",
" <td>0.018</td>\n",
" <td>0.006</td>\n",
" <td>2001-08-29</td>\n",
" <td>20010829</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2190</th>\n",
" <td>20010830</td>\n",
" <td>48013.06</td>\n",
" <td>4.45405</td>\n",
" <td>4.55472</td>\n",
" <td>4.60505</td>\n",
" <td>4.41967</td>\n",
" <td>0.037</td>\n",
" <td>0.029</td>\n",
" <td>0.010</td>\n",
" <td>2001-08-30</td>\n",
" <td>20010830</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2191</th>\n",
" <td>20010831</td>\n",
" <td>23231.48</td>\n",
" <td>4.56086</td>\n",
" <td>4.54367</td>\n",
" <td>4.61856</td>\n",
" <td>4.51789</td>\n",
" <td>0.042</td>\n",
" <td>0.036</td>\n",
" <td>0.016</td>\n",
" <td>2001-08-31</td>\n",
" <td>20010831</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",
" </tr>\n",
" <tr>\n",
" <th>2182</th>\n",
" <td>20241225</td>\n",
" <td>17123.39</td>\n",
" <td>1538.80000</td>\n",
" <td>1530.00000</td>\n",
" <td>1538.80000</td>\n",
" <td>1526.10000</td>\n",
" <td>5.430</td>\n",
" <td>5.063</td>\n",
" <td>2.348</td>\n",
" <td>2024-12-25</td>\n",
" <td>20241225</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2183</th>\n",
" <td>20241226</td>\n",
" <td>18286.51</td>\n",
" <td>1534.00000</td>\n",
" <td>1527.79000</td>\n",
" <td>1538.78000</td>\n",
" <td>1523.00000</td>\n",
" <td>4.192</td>\n",
" <td>4.968</td>\n",
" <td>2.872</td>\n",
" <td>2024-12-26</td>\n",
" <td>20241226</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2184</th>\n",
" <td>20241227</td>\n",
" <td>20759.32</td>\n",
" <td>1528.90000</td>\n",
" <td>1528.97000</td>\n",
" <td>1536.00000</td>\n",
" <td>1519.50000</td>\n",
" <td>3.295</td>\n",
" <td>4.931</td>\n",
" <td>3.283</td>\n",
" <td>2024-12-27</td>\n",
" <td>20241227</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2185</th>\n",
" <td>20241230</td>\n",
" <td>25129.82</td>\n",
" <td>1533.97000</td>\n",
" <td>1525.00000</td>\n",
" <td>1543.96000</td>\n",
" <td>1525.00000</td>\n",
" <td>1.993</td>\n",
" <td>4.529</td>\n",
" <td>3.533</td>\n",
" <td>2024-12-30</td>\n",
" <td>20241230</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2186</th>\n",
" <td>20241231</td>\n",
" <td>39354.45</td>\n",
" <td>1525.40000</td>\n",
" <td>1524.00000</td>\n",
" <td>1545.00000</td>\n",
" <td>1522.01000</td>\n",
" <td>0.880</td>\n",
" <td>4.083</td>\n",
" <td>3.643</td>\n",
" <td>2024-12-31</td>\n",
" <td>20241231</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>5591 rows × 11 columns</p>\n",
"</div>"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"execution_count": 2
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-02-11T06:33:12.365001Z",
"start_time": "2025-02-11T06:33:12.329227Z"
}
},
"cell_type": "code",
"source": [
"import talib\n",
"\n",
"dif, dea, hist = talib.MACD(df[\"close\"], fastperiod=12, slowperiod=26, signalperiod=9)\n",
"\n",
"# 将结果添加到数据框\n",
"df['DIF'] = dif\n",
"df['DEA'] = dea\n",
"df['MACD'] = hist\n",
"\n",
"#根据close列计算macd值\n",
"talib.SMA(df[\"close\"], timeperiod=26, step=10)\n",
"\n",
"df"
],
"id": "72b1c0c3f57e8b8e",
"outputs": [
{
"data": {
"text/plain": [
" date volume open close high low \\\n",
"2187 20010827 406318.00 4.23675 4.36443 4.63820 4.03295 \n",
"2188 20010828 129647.79 4.29568 4.52525 4.54244 4.24902 \n",
"2189 20010829 53252.75 4.53999 4.46632 4.54244 4.43195 \n",
"2190 20010830 48013.06 4.45405 4.55472 4.60505 4.41967 \n",
"2191 20010831 23231.48 4.56086 4.54367 4.61856 4.51789 \n",
"... ... ... ... ... ... ... \n",
"2182 20241225 17123.39 1538.80000 1530.00000 1538.80000 1526.10000 \n",
"2183 20241226 18286.51 1534.00000 1527.79000 1538.78000 1523.00000 \n",
"2184 20241227 20759.32 1528.90000 1528.97000 1536.00000 1519.50000 \n",
"2185 20241230 25129.82 1533.97000 1525.00000 1543.96000 1525.00000 \n",
"2186 20241231 39354.45 1525.40000 1524.00000 1545.00000 1522.01000 \n",
"\n",
" macd macd_dif macd_dea datetime datetime_text DIF DEA \\\n",
"2187 0.000 0.000 0.000 2001-08-27 20010827 NaN NaN \n",
"2188 0.021 0.013 0.003 2001-08-28 20010828 NaN NaN \n",
"2189 0.025 0.018 0.006 2001-08-29 20010829 NaN NaN \n",
"2190 0.037 0.029 0.010 2001-08-30 20010830 NaN NaN \n",
"2191 0.042 0.036 0.016 2001-08-31 20010831 NaN NaN \n",
"... ... ... ... ... ... ... ... \n",
"2182 5.430 5.063 2.348 2024-12-25 20241225 5.062711 2.347629 \n",
"2183 4.192 4.968 2.872 2024-12-26 20241226 4.967756 2.871654 \n",
"2184 3.295 4.931 3.283 2024-12-27 20241227 4.930880 3.283499 \n",
"2185 1.993 4.529 3.533 2024-12-30 20241230 4.529101 3.532620 \n",
"2186 0.880 4.083 3.643 2024-12-31 20241231 4.082931 3.642682 \n",
"\n",
" MACD \n",
"2187 NaN \n",
"2188 NaN \n",
"2189 NaN \n",
"2190 NaN \n",
"2191 NaN \n",
"... ... \n",
"2182 2.715082 \n",
"2183 2.096102 \n",
"2184 1.647381 \n",
"2185 0.996481 \n",
"2186 0.440249 \n",
"\n",
"[5591 rows x 14 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>date</th>\n",
" <th>volume</th>\n",
" <th>open</th>\n",
" <th>close</th>\n",
" <th>high</th>\n",
" <th>low</th>\n",
" <th>macd</th>\n",
" <th>macd_dif</th>\n",
" <th>macd_dea</th>\n",
" <th>datetime</th>\n",
" <th>datetime_text</th>\n",
" <th>DIF</th>\n",
" <th>DEA</th>\n",
" <th>MACD</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>2187</th>\n",
" <td>20010827</td>\n",
" <td>406318.00</td>\n",
" <td>4.23675</td>\n",
" <td>4.36443</td>\n",
" <td>4.63820</td>\n",
" <td>4.03295</td>\n",
" <td>0.000</td>\n",
" <td>0.000</td>\n",
" <td>0.000</td>\n",
" <td>2001-08-27</td>\n",
" <td>20010827</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2188</th>\n",
" <td>20010828</td>\n",
" <td>129647.79</td>\n",
" <td>4.29568</td>\n",
" <td>4.52525</td>\n",
" <td>4.54244</td>\n",
" <td>4.24902</td>\n",
" <td>0.021</td>\n",
" <td>0.013</td>\n",
" <td>0.003</td>\n",
" <td>2001-08-28</td>\n",
" <td>20010828</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2189</th>\n",
" <td>20010829</td>\n",
" <td>53252.75</td>\n",
" <td>4.53999</td>\n",
" <td>4.46632</td>\n",
" <td>4.54244</td>\n",
" <td>4.43195</td>\n",
" <td>0.025</td>\n",
" <td>0.018</td>\n",
" <td>0.006</td>\n",
" <td>2001-08-29</td>\n",
" <td>20010829</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2190</th>\n",
" <td>20010830</td>\n",
" <td>48013.06</td>\n",
" <td>4.45405</td>\n",
" <td>4.55472</td>\n",
" <td>4.60505</td>\n",
" <td>4.41967</td>\n",
" <td>0.037</td>\n",
" <td>0.029</td>\n",
" <td>0.010</td>\n",
" <td>2001-08-30</td>\n",
" <td>20010830</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2191</th>\n",
" <td>20010831</td>\n",
" <td>23231.48</td>\n",
" <td>4.56086</td>\n",
" <td>4.54367</td>\n",
" <td>4.61856</td>\n",
" <td>4.51789</td>\n",
" <td>0.042</td>\n",
" <td>0.036</td>\n",
" <td>0.016</td>\n",
" <td>2001-08-31</td>\n",
" <td>20010831</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</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",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2182</th>\n",
" <td>20241225</td>\n",
" <td>17123.39</td>\n",
" <td>1538.80000</td>\n",
" <td>1530.00000</td>\n",
" <td>1538.80000</td>\n",
" <td>1526.10000</td>\n",
" <td>5.430</td>\n",
" <td>5.063</td>\n",
" <td>2.348</td>\n",
" <td>2024-12-25</td>\n",
" <td>20241225</td>\n",
" <td>5.062711</td>\n",
" <td>2.347629</td>\n",
" <td>2.715082</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2183</th>\n",
" <td>20241226</td>\n",
" <td>18286.51</td>\n",
" <td>1534.00000</td>\n",
" <td>1527.79000</td>\n",
" <td>1538.78000</td>\n",
" <td>1523.00000</td>\n",
" <td>4.192</td>\n",
" <td>4.968</td>\n",
" <td>2.872</td>\n",
" <td>2024-12-26</td>\n",
" <td>20241226</td>\n",
" <td>4.967756</td>\n",
" <td>2.871654</td>\n",
" <td>2.096102</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2184</th>\n",
" <td>20241227</td>\n",
" <td>20759.32</td>\n",
" <td>1528.90000</td>\n",
" <td>1528.97000</td>\n",
" <td>1536.00000</td>\n",
" <td>1519.50000</td>\n",
" <td>3.295</td>\n",
" <td>4.931</td>\n",
" <td>3.283</td>\n",
" <td>2024-12-27</td>\n",
" <td>20241227</td>\n",
" <td>4.930880</td>\n",
" <td>3.283499</td>\n",
" <td>1.647381</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2185</th>\n",
" <td>20241230</td>\n",
" <td>25129.82</td>\n",
" <td>1533.97000</td>\n",
" <td>1525.00000</td>\n",
" <td>1543.96000</td>\n",
" <td>1525.00000</td>\n",
" <td>1.993</td>\n",
" <td>4.529</td>\n",
" <td>3.533</td>\n",
" <td>2024-12-30</td>\n",
" <td>20241230</td>\n",
" <td>4.529101</td>\n",
" <td>3.532620</td>\n",
" <td>0.996481</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2186</th>\n",
" <td>20241231</td>\n",
" <td>39354.45</td>\n",
" <td>1525.40000</td>\n",
" <td>1524.00000</td>\n",
" <td>1545.00000</td>\n",
" <td>1522.01000</td>\n",
" <td>0.880</td>\n",
" <td>4.083</td>\n",
" <td>3.643</td>\n",
" <td>2024-12-31</td>\n",
" <td>20241231</td>\n",
" <td>4.082931</td>\n",
" <td>3.642682</td>\n",
" <td>0.440249</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>5591 rows × 14 columns</p>\n",
"</div>"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"execution_count": 3
}
],
"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
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2,8 +2,8 @@ import os.path
import pandas as pd
# finance_root = "/Users/lanyuanxiaoyao/SynologyDrive/data/Tushare"
finance_root = "C:\\Users\\lanyuanxiaoyao\\Documents\\Tushare"
finance_root = "/Users/lanyuanxiaoyao/SynologyDrive/data/Tushare"
# finance_root = "C:\\Users\\lanyuanxiaoyao\\Documents\\Tushare"
def load_balance_sheet():

View File

@@ -6,25 +6,25 @@
"metadata": {
"collapsed": true,
"ExecuteTime": {
"end_time": "2025-01-19T16:42:26.631868Z",
"start_time": "2025-01-19T16:42:26.628635Z"
"end_time": "2025-01-20T09:12:32.313699Z",
"start_time": "2025-01-20T09:12:32.310753Z"
}
},
"source": [
"import numpy as np\n",
"\n",
"import pandas as pd\n",
"import tushare as ts\n",
"\n",
"ts_pro = ts.pro_api(token=\"64ebff4fa679167600b905ee45dd88e76f3963c0ff39157f3f085f0e\")"
],
"outputs": [],
"execution_count": 459
"execution_count": 99
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-01-19T16:42:27.857016Z",
"start_time": "2025-01-19T16:42:26.639161Z"
"end_time": "2025-01-20T09:12:35.800981Z",
"start_time": "2025-01-20T09:12:32.319361Z"
}
},
"cell_type": "code",
@@ -77,7 +77,7 @@
],
"id": "68b2debc14502fd5",
"outputs": [],
"execution_count": 460
"execution_count": 100
},
{
"metadata": {},
@@ -88,15 +88,15 @@
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-01-19T16:42:27.931899Z",
"start_time": "2025-01-19T16:42:27.868963Z"
"end_time": "2025-01-20T09:12:35.994681Z",
"start_time": "2025-01-20T09:12:35.828990Z"
}
},
"cell_type": "code",
"source": "finance_df = finance_df.groupby(\"code\").filter(lambda x: len(x) > 6)",
"id": "4293bd93ea8f9ed",
"outputs": [],
"execution_count": 461
"execution_count": 101
},
{
"metadata": {},
@@ -118,8 +118,8 @@
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-01-19T16:42:29.192712Z",
"start_time": "2025-01-19T16:42:27.946033Z"
"end_time": "2025-01-20T09:12:38.908153Z",
"start_time": "2025-01-20T09:12:36.022143Z"
}
},
"cell_type": "code",
@@ -151,12 +151,12 @@
"name": "stderr",
"output_type": "stream",
"text": [
"C:\\Users\\lanyuanxiaoyao\\AppData\\Local\\Temp\\ipykernel_28824\\1604170078.py:20: DeprecationWarning: DataFrameGroupBy.apply operated on the grouping columns. This behavior is deprecated, and in a future version of pandas the grouping columns will be excluded from the operation. Either pass `include_groups=False` to exclude the groupings or explicitly select the grouping columns after groupby to silence this warning.\n",
"/var/folders/7h/w0cmp4zj6mn9br_6nyj310m40000gn/T/ipykernel_72996/1604170078.py:20: DeprecationWarning: DataFrameGroupBy.apply operated on the grouping columns. This behavior is deprecated, and in a future version of pandas the grouping columns will be excluded from the operation. Either pass `include_groups=False` to exclude the groupings or explicitly select the grouping columns after groupby to silence this warning.\n",
" finance_df = finance_df.groupby(\"code\").apply(reset_score_for_average_roe).reset_index(drop=True)\n"
]
}
],
"execution_count": 462
"execution_count": 102
},
{
"metadata": {},
@@ -173,8 +173,8 @@
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-01-19T16:42:29.363249Z",
"start_time": "2025-01-19T16:42:29.219453Z"
"end_time": "2025-01-20T09:12:39.103417Z",
"start_time": "2025-01-20T09:12:38.937447Z"
}
},
"cell_type": "code",
@@ -190,7 +190,7 @@
],
"id": "3b585cf8e2eb5e3",
"outputs": [],
"execution_count": 463
"execution_count": 103
},
{
"metadata": {},
@@ -206,8 +206,8 @@
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-01-19T16:42:29.878285Z",
"start_time": "2025-01-19T16:42:29.369862Z"
"end_time": "2025-01-20T09:12:39.922683Z",
"start_time": "2025-01-20T09:12:39.130104Z"
}
},
"cell_type": "code",
@@ -221,7 +221,7 @@
],
"id": "fd5582e080102e20",
"outputs": [],
"execution_count": 464
"execution_count": 104
},
{
"metadata": {},
@@ -237,8 +237,8 @@
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-01-19T16:42:29.905727Z",
"start_time": "2025-01-19T16:42:29.889468Z"
"end_time": "2025-01-20T09:12:39.965030Z",
"start_time": "2025-01-20T09:12:39.946246Z"
}
},
"cell_type": "code",
@@ -258,7 +258,7 @@
],
"id": "bc92e050c82c3768",
"outputs": [],
"execution_count": 465
"execution_count": 105
},
{
"metadata": {},
@@ -282,8 +282,8 @@
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-01-19T16:42:29.923829Z",
"start_time": "2025-01-19T16:42:29.916781Z"
"end_time": "2025-01-20T09:12:40.003327Z",
"start_time": "2025-01-20T09:12:39.990482Z"
}
},
"cell_type": "code",
@@ -312,7 +312,7 @@
],
"id": "baeb44a4fb28b60b",
"outputs": [],
"execution_count": 466
"execution_count": 106
},
{
"metadata": {},
@@ -327,8 +327,8 @@
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-01-19T16:42:30.005541Z",
"start_time": "2025-01-19T16:42:29.935348Z"
"end_time": "2025-01-20T09:12:40.179998Z",
"start_time": "2025-01-20T09:12:40.027705Z"
}
},
"cell_type": "code",
@@ -336,14 +336,15 @@
"finance_df[\"gross_profit_ratio\"] = (finance_df[\"total_revenue\"] - finance_df[\"operating_costs\"]) / finance_df[\n",
" \"total_revenue\"]\n",
"finance_df[\"gross_profit_ratio_std\"] = finance_df.groupby(\"code\")[\"gross_profit_ratio\"].rolling(\n",
" window=5).std().reset_index(0, drop=True)\n",
" window=5\n",
").std().reset_index(0, drop=True)\n",
"finance_df[\"score_gross_profit_ratio\"] = 0\n",
"finance_df[(not finance_df[\"gross_profit_ratio_std\"].isna) & (finance_df[\"gross_profit_ratio_std\"] < 30)] = 50\n",
"finance_df[\"score\"] += finance_df[\"score_gross_profit_ratio\"]"
],
"id": "9d23bdf60a1839c9",
"outputs": [],
"execution_count": 467
"execution_count": 107
},
{
"metadata": {},
@@ -360,8 +361,8 @@
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-01-19T16:42:30.022774Z",
"start_time": "2025-01-19T16:42:30.016550Z"
"end_time": "2025-01-20T09:12:40.213136Z",
"start_time": "2025-01-20T09:12:40.205548Z"
}
},
"cell_type": "code",
@@ -376,7 +377,7 @@
],
"id": "f7d9486af89cb710",
"outputs": [],
"execution_count": 468
"execution_count": 108
},
{
"metadata": {},
@@ -394,8 +395,8 @@
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-01-19T16:42:46.378919Z",
"start_time": "2025-01-19T16:42:30.718209Z"
"end_time": "2025-01-20T09:12:57.833029Z",
"start_time": "2025-01-20T09:12:40.241875Z"
}
},
"cell_type": "code",
@@ -404,28 +405,29 @@
" # 计算 score_net_income_1\n",
" group['net_income_shift_1'] = group['net_income'].shift(1)\n",
" group['score_net_income_1'] = (group['net_income'] > group['net_income_shift_1']).map(\n",
" {True: 30, False: -30})\n",
" group = group.mask(pd.isna(group[\"net_income_shift_1\"]), other=0)\n",
" {True: 30, False: -30}\n",
" )\n",
" # 计算 score_net_income_2\n",
" group['net_income_shift_2'] = group['net_income'].shift(2)\n",
" group['score_net_income_2'] = (group['net_income_shift_1'] > group['net_income_shift_2']).map(\n",
" {True: 25, False: -25})\n",
" {True: 25, False: -25}\n",
" )\n",
" # 计算 score_net_income_3\n",
" group['net_income_shift_3'] = group['net_income'].shift(3)\n",
" group['score_net_income_3'] = (group['net_income_shift_2'] > group['net_income_shift_3']).map(\n",
" {True: 20, False: -20})\n",
" {True: 20, False: -20}\n",
" )\n",
" # 计算 score_net_income_4\n",
" group['net_income_shift_4'] = group['net_income'].shift(4)\n",
" group['score_net_income_4'] = (group['net_income_shift_3'] > group['net_income_shift_4']).map(\n",
" {True: 15, False: -15}).fillna(0)\n",
" {True: 15, False: -15}\n",
" )\n",
" return group\n",
"\n",
"\n",
"finance_df = finance_df.groupby(\"code\").apply(score_by_net_income_ascending).reset_index(drop=True)\n",
"finance_df[\"score_net_income_ascending\"] = np.sum(\n",
" [finance_df[\"score_net_income_1\"], finance_df[\"score_net_income_2\"], finance_df[\"score_net_income_3\"],\n",
" finance_df[\"score_net_income_4\"]], axis=0)\n",
"finance_df"
"finance_df[\"score_net_income_ascending\"] = finance_df[\"score_net_income_1\"] + finance_df[\"score_net_income_2\"] + \\\n",
" finance_df[\"score_net_income_3\"] + finance_df[\"score_net_income_4\"]"
],
"id": "2d1ca7fc7873ce71",
"outputs": [
@@ -433,92 +435,111 @@
"name": "stderr",
"output_type": "stream",
"text": [
"C:\\Users\\lanyuanxiaoyao\\AppData\\Local\\Temp\\ipykernel_28824\\3206398043.py:22: DeprecationWarning: DataFrameGroupBy.apply operated on the grouping columns. This behavior is deprecated, and in a future version of pandas the grouping columns will be excluded from the operation. Either pass `include_groups=False` to exclude the groupings or explicitly select the grouping columns after groupby to silence this warning.\n",
"/var/folders/7h/w0cmp4zj6mn9br_6nyj310m40000gn/T/ipykernel_72996/432379325.py:25: DeprecationWarning: DataFrameGroupBy.apply operated on the grouping columns. This behavior is deprecated, and in a future version of pandas the grouping columns will be excluded from the operation. Either pass `include_groups=False` to exclude the groupings or explicitly select the grouping columns after groupby to silence this warning.\n",
" finance_df = finance_df.groupby(\"code\").apply(score_by_net_income_ascending).reset_index(drop=True)\n"
]
},
}
],
"execution_count": 109
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-01-20T09:13:15.433529Z",
"start_time": "2025-01-20T09:12:57.864097Z"
}
},
"cell_type": "code",
"source": [
"def score_by_operating_net_cash_flow_ascending(group):\n",
" # 计算 score_operating_net_cash_flow_1\n",
" group['operating_net_cash_flow_shift_1'] = group['operating_net_cash_flow'].shift(1)\n",
" group['score_operating_net_cash_flow_1'] = (\n",
" group['operating_net_cash_flow'] > group['operating_net_cash_flow_shift_1']).map(\n",
" {True: 30, False: -30}\n",
" )\n",
" # 计算 score_operating_net_cash_flow_2\n",
" group['operating_net_cash_flow_shift_2'] = group['operating_net_cash_flow'].shift(2)\n",
" group['score_operating_net_cash_flow_2'] = (\n",
" group['operating_net_cash_flow_shift_1'] > group['operating_net_cash_flow_shift_2']).map(\n",
" {True: 25, False: -25}\n",
" )\n",
" # 计算 score_operating_net_cash_flow_3\n",
" group['operating_net_cash_flow_shift_3'] = group['operating_net_cash_flow'].shift(3)\n",
" group['score_operating_net_cash_flow_3'] = (\n",
" group['operating_net_cash_flow_shift_2'] > group['operating_net_cash_flow_shift_3']).map(\n",
" {True: 20, False: -20}\n",
" )\n",
" # 计算 score_operating_net_cash_flow_4\n",
" group['operating_net_cash_flow_shift_4'] = group['operating_net_cash_flow'].shift(4)\n",
" group['score_operating_net_cash_flow_4'] = (\n",
" group['operating_net_cash_flow_shift_3'] > group['operating_net_cash_flow_shift_4']).map(\n",
" {True: 15, False: -15}\n",
" )\n",
" return group\n",
"\n",
"\n",
"finance_df = finance_df.groupby(\"code\").apply(score_by_operating_net_cash_flow_ascending).reset_index(drop=True)\n",
"finance_df[\"score_operating_net_cash_flow_ascending\"] = finance_df[\"score_operating_net_cash_flow_1\"] + finance_df[\n",
" \"score_operating_net_cash_flow_2\"] + finance_df[\"score_operating_net_cash_flow_3\"] + finance_df[\n",
" \"score_operating_net_cash_flow_4\"]"
],
"id": "a90f3721487bd635",
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/var/folders/7h/w0cmp4zj6mn9br_6nyj310m40000gn/T/ipykernel_72996/2138932640.py:29: DeprecationWarning: DataFrameGroupBy.apply operated on the grouping columns. This behavior is deprecated, and in a future version of pandas the grouping columns will be excluded from the operation. Either pass `include_groups=False` to exclude the groupings or explicitly select the grouping columns after groupby to silence this warning.\n",
" finance_df = finance_df.groupby(\"code\").apply(score_by_operating_net_cash_flow_ascending).reset_index(drop=True)\n"
]
}
],
"execution_count": 110
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2025-01-20T09:21:47.276162Z",
"start_time": "2025-01-20T09:21:47.130339Z"
}
},
"cell_type": "code",
"source": [
"result_df = finance_df.sort_values(by=['score'], ascending=False, inplace=False)[[\"code\", \"score\"]]\n",
"result_df = result_df.drop_duplicates(\"code\")\n",
"# result_df[:20]\n",
"\n",
"stock_df = pd.read_csv(\"../材料/股票基础信息.csv\")[[\"ts_code\", \"name\"]]\n",
"result_df = result_df.merge(stock_df, left_on=\"code\", right_on=\"ts_code\")\n",
"result_df[:20]"
],
"id": "ef9e6259efc1c1d0",
"outputs": [
{
"data": {
"text/plain": [
" code year total_stockholder_interest net_income \\\n",
"0 0 0 0.000000e+00 0.000000e+00 \n",
"1 000001.SZ 2006 6.474463e+09 1.302907e+09 \n",
"2 000001.SZ 2007 1.300606e+10 2.649903e+09 \n",
"3 000001.SZ 2008 1.640079e+10 6.140350e+08 \n",
"4 000001.SZ 2009 2.046961e+10 5.030729e+09 \n",
"... ... ... ... ... \n",
"70725 871981.BJ 2019 1.484536e+08 1.933833e+07 \n",
"70726 871981.BJ 2020 1.963500e+08 3.113004e+07 \n",
"70727 871981.BJ 2021 4.901179e+08 6.549797e+07 \n",
"70728 871981.BJ 2022 5.238630e+08 4.359533e+07 \n",
"70729 871981.BJ 2023 5.044336e+08 -5.665176e+06 \n",
"\n",
" total_assets total_revenue inventories accounts_receivable \\\n",
"0 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 \n",
"1 2.605763e+11 7.135218e+09 NaN NaN \n",
"2 3.525394e+11 1.080750e+10 NaN NaN \n",
"3 4.744402e+11 1.451312e+10 NaN NaN \n",
"4 5.878110e+11 1.511444e+10 NaN NaN \n",
"... ... ... ... ... \n",
"70725 3.438787e+08 2.288707e+08 6.439933e+07 9.145441e+07 \n",
"70726 4.407381e+08 3.221584e+08 7.076865e+07 1.028702e+08 \n",
"70727 7.806398e+08 4.748939e+08 1.102946e+08 1.094223e+08 \n",
"70728 8.141886e+08 3.872667e+08 1.034502e+08 7.252802e+07 \n",
"70729 7.671820e+08 3.613133e+08 1.070212e+08 7.962033e+07 \n",
"\n",
" operating_costs operating_profit ... score_operating_safety_margin \\\n",
"0 0.000000e+00 0.000000e+00 ... 0 \n",
"1 NaN 1.905169e+09 ... 0 \n",
"2 NaN 3.721942e+09 ... 0 \n",
"3 NaN 8.034260e+08 ... 0 \n",
"4 NaN 6.159127e+09 ... 0 \n",
"... ... ... ... ... \n",
"70725 1.759984e+08 1.982603e+07 ... 0 \n",
"70726 2.444144e+08 3.466142e+07 ... 0 \n",
"70727 3.501988e+08 7.194507e+07 ... 0 \n",
"70728 3.141146e+08 2.827675e+07 ... 0 \n",
"70729 3.220560e+08 -1.192680e+07 ... 0 \n",
"\n",
" net_income_shift_1 score_net_income_1 net_income_shift_2 \\\n",
"0 0.000000e+00 0 NaN \n",
"1 3.110076e+08 30 NaN \n",
"2 1.302907e+09 30 0.000000e+00 \n",
"3 2.649903e+09 -30 1.302907e+09 \n",
"4 6.140350e+08 30 2.649903e+09 \n",
"... ... ... ... \n",
"70725 1.875294e+07 30 9.625220e+06 \n",
"70726 1.933833e+07 30 1.875294e+07 \n",
"70727 3.113004e+07 30 1.933833e+07 \n",
"70728 6.549797e+07 -30 3.113004e+07 \n",
"70729 4.359533e+07 -30 6.549797e+07 \n",
"\n",
" score_net_income_2 net_income_shift_3 score_net_income_3 \\\n",
"0 -25 NaN -20 \n",
"1 -25 NaN -20 \n",
"2 25 NaN -20 \n",
"3 25 0.000000e+00 20 \n",
"4 -25 1.302907e+09 20 \n",
"... ... ... ... \n",
"70725 25 0.000000e+00 20 \n",
"70726 25 9.625220e+06 20 \n",
"70727 25 1.875294e+07 20 \n",
"70728 25 1.933833e+07 20 \n",
"70729 -25 3.113004e+07 20 \n",
"\n",
" net_income_shift_4 score_net_income_4 score_net_income_ascending \n",
"0 NaN -15 -60 \n",
"1 NaN -15 -30 \n",
"2 NaN -15 20 \n",
"3 NaN -15 0 \n",
"4 0.00 15 40 \n",
"... ... ... ... \n",
"70725 NaN -15 60 \n",
"70726 0.00 15 90 \n",
"70727 9625220.11 15 90 \n",
"70728 18752944.38 15 30 \n",
"70729 19338331.78 15 -20 \n",
"\n",
"[70730 rows x 46 columns]"
" code score ts_code name\n",
"0 600519.SH 810 600519.SH 贵州茅台\n",
"1 600309.SH 810 600309.SH 万华化学\n",
"2 601919.SH 790 601919.SH 中远海控\n",
"3 002415.SZ 750 002415.SZ 海康威视\n",
"4 000651.SZ 710 000651.SZ 格力电器\n",
"5 603868.SH 710 603868.SH 飞科电器\n",
"6 601225.SH 710 601225.SH 陕西煤业\n",
"7 000672.SZ 710 000672.SZ 上峰水泥\n",
"8 000568.SZ 710 000568.SZ 泸州老窖\n",
"9 001201.SZ 710 001201.SZ 东瑞股份\n",
"10 300390.SZ 710 300390.SZ 天华新能\n",
"11 605098.SH 710 605098.SH 行动教育\n",
"12 600398.SH 710 600398.SH 海澜之家\n",
"13 605089.SH 710 605089.SH 味知香\n",
"14 603816.SH 710 603816.SH 顾家家居\n",
"15 600507.SH 710 600507.SH 方大特钢\n",
"16 300533.SZ 710 300533.SZ 冰川网络\n",
"17 300146.SZ 710 300146.SZ 汤臣倍健\n",
"18 300677.SZ 710 300677.SZ 英科医疗\n",
"19 605117.SH 710 605117.SH 德业股份"
],
"text/html": [
"<div>\n",
@@ -540,439 +561,163 @@
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>code</th>\n",
" <th>year</th>\n",
" <th>total_stockholder_interest</th>\n",
" <th>net_income</th>\n",
" <th>total_assets</th>\n",
" <th>total_revenue</th>\n",
" <th>inventories</th>\n",
" <th>accounts_receivable</th>\n",
" <th>operating_costs</th>\n",
" <th>operating_profit</th>\n",
" <th>...</th>\n",
" <th>score_operating_safety_margin</th>\n",
" <th>net_income_shift_1</th>\n",
" <th>score_net_income_1</th>\n",
" <th>net_income_shift_2</th>\n",
" <th>score_net_income_2</th>\n",
" <th>net_income_shift_3</th>\n",
" <th>score_net_income_3</th>\n",
" <th>net_income_shift_4</th>\n",
" <th>score_net_income_4</th>\n",
" <th>score_net_income_ascending</th>\n",
" <th>score</th>\n",
" <th>ts_code</th>\n",
" <th>name</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.000000e+00</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0</td>\n",
" <td>NaN</td>\n",
" <td>-25</td>\n",
" <td>NaN</td>\n",
" <td>-20</td>\n",
" <td>NaN</td>\n",
" <td>-15</td>\n",
" <td>-60</td>\n",
" <td>600519.SH</td>\n",
" <td>810</td>\n",
" <td>600519.SH</td>\n",
" <td>贵州茅台</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>000001.SZ</td>\n",
" <td>2006</td>\n",
" <td>6.474463e+09</td>\n",
" <td>1.302907e+09</td>\n",
" <td>2.605763e+11</td>\n",
" <td>7.135218e+09</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.905169e+09</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>3.110076e+08</td>\n",
" <td>30</td>\n",
" <td>NaN</td>\n",
" <td>-25</td>\n",
" <td>NaN</td>\n",
" <td>-20</td>\n",
" <td>NaN</td>\n",
" <td>-15</td>\n",
" <td>-30</td>\n",
" <td>600309.SH</td>\n",
" <td>810</td>\n",
" <td>600309.SH</td>\n",
" <td>万华化学</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>000001.SZ</td>\n",
" <td>2007</td>\n",
" <td>1.300606e+10</td>\n",
" <td>2.649903e+09</td>\n",
" <td>3.525394e+11</td>\n",
" <td>1.080750e+10</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>3.721942e+09</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>1.302907e+09</td>\n",
" <td>30</td>\n",
" <td>0.000000e+00</td>\n",
" <td>25</td>\n",
" <td>NaN</td>\n",
" <td>-20</td>\n",
" <td>NaN</td>\n",
" <td>-15</td>\n",
" <td>20</td>\n",
" <td>601919.SH</td>\n",
" <td>790</td>\n",
" <td>601919.SH</td>\n",
" <td>中远海控</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>000001.SZ</td>\n",
" <td>2008</td>\n",
" <td>1.640079e+10</td>\n",
" <td>6.140350e+08</td>\n",
" <td>4.744402e+11</td>\n",
" <td>1.451312e+10</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>8.034260e+08</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>2.649903e+09</td>\n",
" <td>-30</td>\n",
" <td>1.302907e+09</td>\n",
" <td>25</td>\n",
" <td>0.000000e+00</td>\n",
" <td>20</td>\n",
" <td>NaN</td>\n",
" <td>-15</td>\n",
" <td>0</td>\n",
" <td>002415.SZ</td>\n",
" <td>750</td>\n",
" <td>002415.SZ</td>\n",
" <td>海康威视</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>000001.SZ</td>\n",
" <td>2009</td>\n",
" <td>2.046961e+10</td>\n",
" <td>5.030729e+09</td>\n",
" <td>5.878110e+11</td>\n",
" <td>1.511444e+10</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>6.159127e+09</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>6.140350e+08</td>\n",
" <td>30</td>\n",
" <td>2.649903e+09</td>\n",
" <td>-25</td>\n",
" <td>1.302907e+09</td>\n",
" <td>20</td>\n",
" <td>0.00</td>\n",
" <td>15</td>\n",
" <td>40</td>\n",
" <td>000651.SZ</td>\n",
" <td>710</td>\n",
" <td>000651.SZ</td>\n",
" <td>格力电器</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",
" <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",
" <th>5</th>\n",
" <td>603868.SH</td>\n",
" <td>710</td>\n",
" <td>603868.SH</td>\n",
" <td>飞科电器</td>\n",
" </tr>\n",
" <tr>\n",
" <th>70725</th>\n",
" <td>871981.BJ</td>\n",
" <td>2019</td>\n",
" <td>1.484536e+08</td>\n",
" <td>1.933833e+07</td>\n",
" <td>3.438787e+08</td>\n",
" <td>2.288707e+08</td>\n",
" <td>6.439933e+07</td>\n",
" <td>9.145441e+07</td>\n",
" <td>1.759984e+08</td>\n",
" <td>1.982603e+07</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>1.875294e+07</td>\n",
" <td>30</td>\n",
" <td>9.625220e+06</td>\n",
" <td>25</td>\n",
" <td>0.000000e+00</td>\n",
" <td>20</td>\n",
" <td>NaN</td>\n",
" <td>-15</td>\n",
" <td>60</td>\n",
" <th>6</th>\n",
" <td>601225.SH</td>\n",
" <td>710</td>\n",
" <td>601225.SH</td>\n",
" <td>陕西煤业</td>\n",
" </tr>\n",
" <tr>\n",
" <th>70726</th>\n",
" <td>871981.BJ</td>\n",
" <td>2020</td>\n",
" <td>1.963500e+08</td>\n",
" <td>3.113004e+07</td>\n",
" <td>4.407381e+08</td>\n",
" <td>3.221584e+08</td>\n",
" <td>7.076865e+07</td>\n",
" <td>1.028702e+08</td>\n",
" <td>2.444144e+08</td>\n",
" <td>3.466142e+07</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>1.933833e+07</td>\n",
" <td>30</td>\n",
" <td>1.875294e+07</td>\n",
" <td>25</td>\n",
" <td>9.625220e+06</td>\n",
" <td>20</td>\n",
" <td>0.00</td>\n",
" <td>15</td>\n",
" <td>90</td>\n",
" <th>7</th>\n",
" <td>000672.SZ</td>\n",
" <td>710</td>\n",
" <td>000672.SZ</td>\n",
" <td>上峰水泥</td>\n",
" </tr>\n",
" <tr>\n",
" <th>70727</th>\n",
" <td>871981.BJ</td>\n",
" <td>2021</td>\n",
" <td>4.901179e+08</td>\n",
" <td>6.549797e+07</td>\n",
" <td>7.806398e+08</td>\n",
" <td>4.748939e+08</td>\n",
" <td>1.102946e+08</td>\n",
" <td>1.094223e+08</td>\n",
" <td>3.501988e+08</td>\n",
" <td>7.194507e+07</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>3.113004e+07</td>\n",
" <td>30</td>\n",
" <td>1.933833e+07</td>\n",
" <td>25</td>\n",
" <td>1.875294e+07</td>\n",
" <td>20</td>\n",
" <td>9625220.11</td>\n",
" <td>15</td>\n",
" <td>90</td>\n",
" <th>8</th>\n",
" <td>000568.SZ</td>\n",
" <td>710</td>\n",
" <td>000568.SZ</td>\n",
" <td>泸州老窖</td>\n",
" </tr>\n",
" <tr>\n",
" <th>70728</th>\n",
" <td>871981.BJ</td>\n",
" <td>2022</td>\n",
" <td>5.238630e+08</td>\n",
" <td>4.359533e+07</td>\n",
" <td>8.141886e+08</td>\n",
" <td>3.872667e+08</td>\n",
" <td>1.034502e+08</td>\n",
" <td>7.252802e+07</td>\n",
" <td>3.141146e+08</td>\n",
" <td>2.827675e+07</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>6.549797e+07</td>\n",
" <td>-30</td>\n",
" <td>3.113004e+07</td>\n",
" <td>25</td>\n",
" <td>1.933833e+07</td>\n",
" <td>20</td>\n",
" <td>18752944.38</td>\n",
" <td>15</td>\n",
" <td>30</td>\n",
" <th>9</th>\n",
" <td>001201.SZ</td>\n",
" <td>710</td>\n",
" <td>001201.SZ</td>\n",
" <td>东瑞股份</td>\n",
" </tr>\n",
" <tr>\n",
" <th>70729</th>\n",
" <td>871981.BJ</td>\n",
" <td>2023</td>\n",
" <td>5.044336e+08</td>\n",
" <td>-5.665176e+06</td>\n",
" <td>7.671820e+08</td>\n",
" <td>3.613133e+08</td>\n",
" <td>1.070212e+08</td>\n",
" <td>7.962033e+07</td>\n",
" <td>3.220560e+08</td>\n",
" <td>-1.192680e+07</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>4.359533e+07</td>\n",
" <td>-30</td>\n",
" <td>6.549797e+07</td>\n",
" <td>-25</td>\n",
" <td>3.113004e+07</td>\n",
" <td>20</td>\n",
" <td>19338331.78</td>\n",
" <td>15</td>\n",
" <td>-20</td>\n",
" <th>10</th>\n",
" <td>300390.SZ</td>\n",
" <td>710</td>\n",
" <td>300390.SZ</td>\n",
" <td>天华新能</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11</th>\n",
" <td>605098.SH</td>\n",
" <td>710</td>\n",
" <td>605098.SH</td>\n",
" <td>行动教育</td>\n",
" </tr>\n",
" <tr>\n",
" <th>12</th>\n",
" <td>600398.SH</td>\n",
" <td>710</td>\n",
" <td>600398.SH</td>\n",
" <td>海澜之家</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13</th>\n",
" <td>605089.SH</td>\n",
" <td>710</td>\n",
" <td>605089.SH</td>\n",
" <td>味知香</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14</th>\n",
" <td>603816.SH</td>\n",
" <td>710</td>\n",
" <td>603816.SH</td>\n",
" <td>顾家家居</td>\n",
" </tr>\n",
" <tr>\n",
" <th>15</th>\n",
" <td>600507.SH</td>\n",
" <td>710</td>\n",
" <td>600507.SH</td>\n",
" <td>方大特钢</td>\n",
" </tr>\n",
" <tr>\n",
" <th>16</th>\n",
" <td>300533.SZ</td>\n",
" <td>710</td>\n",
" <td>300533.SZ</td>\n",
" <td>冰川网络</td>\n",
" </tr>\n",
" <tr>\n",
" <th>17</th>\n",
" <td>300146.SZ</td>\n",
" <td>710</td>\n",
" <td>300146.SZ</td>\n",
" <td>汤臣倍健</td>\n",
" </tr>\n",
" <tr>\n",
" <th>18</th>\n",
" <td>300677.SZ</td>\n",
" <td>710</td>\n",
" <td>300677.SZ</td>\n",
" <td>英科医疗</td>\n",
" </tr>\n",
" <tr>\n",
" <th>19</th>\n",
" <td>605117.SH</td>\n",
" <td>710</td>\n",
" <td>605117.SH</td>\n",
" <td>德业股份</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>70730 rows × 46 columns</p>\n",
"</div>"
]
},
"execution_count": 469,
"execution_count": 118,
"metadata": {},
"output_type": "execute_result"
}
],
"execution_count": 469
},
{
"metadata": {},
"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": null
},
{
"metadata": {},
"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": null
},
{
"metadata": {},
"cell_type": "code",
"source": [
"df = pd.DataFrame(\n",
" 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",
")\n",
"df.sort_values(by=\"score\", ascending=False, inplace=True)\n",
"df"
],
"id": "ef9e6259efc1c1d0",
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": "df[:100][\"code\"]",
"id": "32b5b4778985afaa",
"outputs": [],
"execution_count": null
},
{
"metadata": {},
"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": [],
"execution_count": null
},
{
"metadata": {},
"cell_type": "code",
"source": [
"temp_df = ts_pro.fina_indicator(\n",
" ts_code=\"600763.SH\", start_date=\"20140101\", end_date=\"20241231\",\n",
" fields=\"ts_code,end_date,roe,roa\"\n",
")\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",
"outputs": [],
"execution_count": null
"execution_count": 118
}
],
"metadata": {