feat: 完善 QMT 交易模块

This commit is contained in:
2026-02-24 13:06:14 +08:00
parent 29706da299
commit 5628fbb34c
13 changed files with 1249 additions and 5368 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -83,32 +83,32 @@
"output_type": "stream",
"text": [
" ts_code trade_date close open high low \\\n",
"0 000905.SH 20260206 8146.4128 8054.2180 8247.2968 8014.6599 \n",
"1 000905.SH 20260205 8146.1073 8203.0627 8224.7847 8081.4283 \n",
"2 000905.SH 20260204 8299.0574 8270.8420 8309.8579 8179.3522 \n",
"3 000905.SH 20260203 8286.7005 8135.8699 8286.7005 8075.3738 \n",
"4 000905.SH 20260202 8037.0456 8279.7152 8324.4341 8032.3500 \n",
"0 000905.SH 20260213 8299.5850 8366.3327 8419.7618 8290.8388 \n",
"1 000905.SH 20260212 8423.5695 8342.3650 8437.4202 8341.7705 \n",
"2 000905.SH 20260211 8325.8107 8295.3326 8373.5033 8295.1223 \n",
"3 000905.SH 20260210 8306.4448 8318.5325 8331.9858 8258.1519 \n",
"4 000905.SH 20260209 8311.2829 8280.1088 8313.4692 8229.0026 \n",
"... ... ... ... ... ... ... \n",
"14059 399006.SZ 20100607 1069.4680 1005.0280 1075.2250 1001.7020 \n",
"14060 399006.SZ 20100604 1027.6810 989.6810 1027.6810 986.5040 \n",
"14061 399006.SZ 20100603 998.3940 1002.3550 1026.7020 997.7750 \n",
"14062 399006.SZ 20100602 997.1190 967.6090 997.1190 952.6110 \n",
"14063 399006.SZ 20100601 973.2330 986.0150 994.7930 948.1180 \n",
"14074 399006.SZ 20100607 1069.4680 1005.0280 1075.2250 1001.7020 \n",
"14075 399006.SZ 20100604 1027.6810 989.6810 1027.6810 986.5040 \n",
"14076 399006.SZ 20100603 998.3940 1002.3550 1026.7020 997.7750 \n",
"14077 399006.SZ 20100602 997.1190 967.6090 997.1190 952.6110 \n",
"14078 399006.SZ 20100601 973.2330 986.0150 994.7930 948.1180 \n",
"\n",
" pre_close change pct_chg vol amount \n",
"0 8146.1073 0.3055 0.0038 2.186421e+08 4.183734e+08 \n",
"1 8299.0574 -152.9501 -1.8430 2.318405e+08 4.352777e+08 \n",
"2 8286.7005 12.3569 0.1491 2.688603e+08 5.018867e+08 \n",
"3 8037.0456 249.6549 3.1063 2.722271e+08 5.432645e+08 \n",
"4 8370.5203 -333.4747 -3.9839 2.996460e+08 5.460557e+08 \n",
"0 8423.5695 -123.9845 -1.4719 2.027857e+08 4.063205e+08 \n",
"1 8325.8107 97.7588 1.1742 2.121383e+08 4.383205e+08 \n",
"2 8306.4448 19.3659 0.2331 2.040197e+08 3.886124e+08 \n",
"3 8311.2829 -4.8381 -0.0582 1.958062e+08 3.942833e+08 \n",
"4 8146.4128 164.8701 2.0238 2.116676e+08 4.279823e+08 \n",
"... ... ... ... ... ... \n",
"14059 1027.6810 41.7870 4.0661 2.655275e+06 9.106095e+06 \n",
"14060 998.3940 29.2870 2.9334 1.500295e+06 5.269441e+06 \n",
"14061 997.1190 1.2750 0.1279 1.616805e+06 6.240835e+06 \n",
"14062 973.2330 23.8860 2.4543 1.074628e+06 4.001206e+06 \n",
"14063 1000.0000 -26.7670 -2.6767 1.356285e+06 4.924177e+06 \n",
"14074 1027.6810 41.7870 4.0661 2.655275e+06 9.106095e+06 \n",
"14075 998.3940 29.2870 2.9334 1.500295e+06 5.269441e+06 \n",
"14076 997.1190 1.2750 0.1279 1.616805e+06 6.240835e+06 \n",
"14077 973.2330 23.8860 2.4543 1.074628e+06 4.001206e+06 \n",
"14078 1000.0000 -26.7670 -2.6767 1.356285e+06 4.924177e+06 \n",
"\n",
"[14064 rows x 11 columns]\n"
"[14079 rows x 11 columns]\n"
]
}
],
@@ -137,7 +137,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.11"
"version": "3.13.2"
}
},
"nbformat": 4,

View File

@@ -39,15 +39,15 @@
"3 000006.SZ 20250312\n",
"4 000007.SZ 20250312\n",
"... ... ...\n",
"27312 920978.BJ 20260126\n",
"27313 920981.BJ 20260126\n",
"27314 920982.BJ 20260126\n",
"27315 920985.BJ 20260126\n",
"27316 920992.BJ 20260126\n",
"27325 920978.BJ 20260202\n",
"27326 920981.BJ 20260202\n",
"27327 920982.BJ 20260202\n",
"27328 920985.BJ 20260202\n",
"27329 920992.BJ 20260202\n",
"\n",
"[8652365 rows x 2 columns]\n",
"20260130\n",
"start_date: 20260202\n"
"[8679695 rows x 2 columns]\n",
"20260206\n",
"start_date: 20260209\n"
]
}
],
@@ -86,27 +86,22 @@
"name": "stdout",
"output_type": "stream",
"text": [
"任务 20260309 完成\n",
"任务 20260310 完成\n",
"任务 20260309 完成\n",
"任务 20260306 完成\n",
"任务 20260305 完成\n",
"任务 20260304 完成\n",
"任务 20260303 完成\n",
"任务 20260227 完成\n",
"任务 20260302 完成\n",
"任务 20260227 完成\n",
"任务 20260226 完成\n",
"任务 20260225 完成\n",
"任务 20260224 完成\n",
"任务 20260213 完成\n",
"任务 20260212 完成\n",
"任务 20260211 完成\n",
"任务 20260209 完成\n",
"任务 20260210 完成\n",
"任务 20260205 完成\n",
"任务 20260206 完成\n",
"任务 20260204 完成\n",
"任务 20260203 完成\n",
"任务 20260202 完成\n"
"任务 20260209 完成\n"
]
}
],
@@ -188,7 +183,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.11"
"version": "3.13.2"
}
},
"nbformat": 4,

View File

@@ -39,15 +39,15 @@
"3 801005.SI 20250221\n",
"4 801010.SI 20250221\n",
"... ... ...\n",
"2190 859811.SI 20260126\n",
"2191 859821.SI 20260126\n",
"2192 859822.SI 20260126\n",
"2193 859852.SI 20260126\n",
"2194 859951.SI 20260126\n",
"2190 859811.SI 20260202\n",
"2191 859821.SI 20260202\n",
"2192 859822.SI 20260202\n",
"2193 859852.SI 20260202\n",
"2194 859951.SI 20260202\n",
"\n",
"[1145363 rows x 2 columns]\n",
"20260130\n",
"start_date: 20260202\n"
"[1147558 rows x 2 columns]\n",
"20260206\n",
"start_date: 20260209\n"
]
}
],
@@ -86,8 +86,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
"任务 20260309 完成\n",
"任务 20260310 完成\n",
"任务 20260309 完成\n",
"任务 20260306 完成\n",
"任务 20260305 完成\n",
"任务 20260304 完成\n",
@@ -98,15 +98,10 @@
"任务 20260225 完成\n",
"任务 20260224 完成\n",
"任务 20260213 完成\n",
"任务 20260211 完成\n",
"任务 20260212 完成\n",
"任务 20260211 完成\n",
"任务 20260210 完成\n",
"任务 20260209 完成\n",
"任务 20260206 完成\n",
"任务 20260205 完成\n",
"任务 20260204 完成\n",
"任务 20260203 完成\n",
"任务 20260202 完成\n"
"任务 20260209 完成\n"
]
}
],
@@ -188,7 +183,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.11"
"version": "3.13.2"
}
},
"nbformat": 4,

View File

@@ -94,17 +94,17 @@
"output_type": "stream",
"text": [
"<class 'pandas.core.frame.DataFrame'>\n",
"Index: 9602310 entries, 0 to 27316\n",
"Index: 9629640 entries, 0 to 27329\n",
"Data columns (total 2 columns):\n",
" # Column Dtype \n",
"--- ------ ----- \n",
" 0 ts_code object\n",
" 1 trade_date object\n",
"dtypes: object(2)\n",
"memory usage: 219.8+ MB\n",
"memory usage: 220.4+ MB\n",
"None\n",
"20260130\n",
"20260202\n"
"20260206\n",
"20260209\n"
]
}
],
@@ -146,8 +146,8 @@
"text": [
"任务 20260309 完成\n",
"任务 20260310 完成\n",
"任务 20260305 完成\n",
"任务 20260306 完成\n",
"任务 20260305 完成\n",
"任务 20260303 完成\n",
"任务 20260304 完成\n",
"任务 20260302 完成\n",
@@ -159,12 +159,7 @@
"任务 20260212 完成\n",
"任务 20260211 完成\n",
"任务 20260210 完成\n",
"任务 20260209 完成\n",
"任务 20260206 完成\n",
"任务 20260205 完成\n",
"任务 20260204 完成\n",
"任务 20260203 完成\n",
"任务 20260202 完成\n"
"任务 20260209 完成\n"
]
}
],
@@ -234,59 +229,59 @@
"name": "stdout",
"output_type": "stream",
"text": [
" ts_code trade_date close turnover_rate turnover_rate_f \\\n",
"0 001389.SZ 20260206 99.50 6.1259 6.1259 \n",
"1 600841.SH 20260206 9.55 4.4177 14.0519 \n",
"2 300968.SZ 20260206 13.71 1.0258 2.1909 \n",
"3 300634.SZ 20260206 28.46 4.0862 6.8510 \n",
"4 300295.SZ 20260206 11.99 3.5950 3.8451 \n",
"... ... ... ... ... ... \n",
"27325 603766.SH 20260202 14.89 1.1630 1.9407 \n",
"27326 603408.SH 20260202 12.92 0.7963 3.0049 \n",
"27327 000004.SZ 20260202 11.99 0.2338 0.3161 \n",
"27328 601628.SH 20260202 48.34 0.1384 1.9210 \n",
"27329 301042.SZ 20260202 86.10 3.6207 5.4797 \n",
" ts_code trade_date close turnover_rate turnover_rate_f \\\n",
"0 001301.SZ 20260213 78.24 1.0939 1.3757 \n",
"1 301050.SZ 20260213 53.61 2.8931 3.6211 \n",
"2 000829.SZ 20260213 10.58 2.2336 3.5271 \n",
"3 688498.SH 20260213 746.98 3.4302 4.7903 \n",
"4 920510.BJ 20260213 18.30 2.8519 4.1749 \n",
"... ... ... ... ... ... \n",
"27350 000065.SZ 20260209 12.07 1.7167 3.2552 \n",
"27351 920249.BJ 20260209 13.86 3.2235 3.3218 \n",
"27352 300824.SZ 20260209 11.36 1.2161 3.0644 \n",
"27353 000766.SZ 20260209 23.65 1.8680 2.3253 \n",
"27354 000591.SZ 20260209 5.72 5.9341 9.0727 \n",
"\n",
" volume_ratio pe pe_ttm pb ps ps_ttm dv_ratio \\\n",
"0 0.83 62.6474 46.6770 11.6304 11.3424 8.6639 0.4819 \n",
"1 1.02 NaN NaN 4.1908 2.0493 2.4531 NaN \n",
"2 0.80 106.8945 225.1215 2.9871 4.6434 4.4246 0.3647 \n",
"3 0.68 55.7987 55.5119 4.4068 7.7725 7.2020 0.5590 \n",
"4 0.40 NaN NaN 2.0169 18.5210 23.1598 NaN \n",
"... ... ... ... ... ... ... ... \n",
"27325 1.04 27.2701 16.9932 3.2106 1.8177 1.5958 2.6864 \n",
"27326 0.99 11.9989 13.3289 1.7275 1.1550 1.1674 3.8700 \n",
"27327 0.05 NaN NaN 42.9590 16.0879 21.5107 NaN \n",
"27328 0.95 12.7771 8.0270 2.2069 2.5849 2.1373 1.4233 \n",
"27329 1.92 84.1572 534.3244 5.7108 8.6920 12.7424 NaN \n",
" volume_ratio pe pe_ttm pb ps ps_ttm \\\n",
"0 0.51 24.3404 20.9997 3.0175 3.9021 2.8680 \n",
"1 0.80 38.6753 105.5089 4.2033 11.2338 18.9830 \n",
"2 0.65 347.7936 NaN 3.7189 0.1291 0.1352 \n",
"3 0.66 NaN 640.0343 29.5658 254.5923 140.4090 \n",
"4 1.41 160.0964 NaN 8.4111 14.5063 16.3558 \n",
"... ... ... ... ... ... ... \n",
"27350 0.73 13.3573 18.0503 1.2589 0.7347 0.9425 \n",
"27351 0.85 NaN NaN 8.0159 2.9840 2.5496 \n",
"27352 0.87 53.3349 33.5338 4.9536 4.9192 3.9029 \n",
"27353 0.75 405.0086 397.6822 9.9329 17.2829 18.3415 \n",
"27354 1.27 18.3189 21.1797 0.9314 3.7171 4.1825 \n",
"\n",
" dv_ttm total_share float_share free_share total_mv \\\n",
"0 0.4819 4.256875e+04 1.511580e+04 15115.7957 4.235591e+06 \n",
"1 NaN 1.387822e+05 1.043024e+05 32790.9410 1.325370e+06 \n",
"2 0.3647 4.133800e+04 4.133800e+04 19355.6537 5.667440e+05 \n",
"3 0.5590 4.512109e+04 4.345735e+04 25919.5274 1.284146e+06 \n",
"4 NaN 1.896137e+04 1.675259e+04 15662.9042 2.273468e+05 \n",
"... ... ... ... ... ... \n",
"27325 4.0296 2.053542e+05 2.053542e+05 123065.9980 3.057724e+06 \n",
"27326 5.3406 4.475730e+04 4.475730e+04 11860.1633 5.782643e+05 \n",
"27327 NaN 1.323803e+04 1.262878e+04 9339.3580 1.587240e+05 \n",
"27328 1.4233 2.826470e+06 2.082353e+06 150000.0000 1.366316e+08 \n",
"27329 NaN 6.972358e+03 6.602083e+03 4362.2827 6.003200e+05 \n",
" dv_ratio dv_ttm total_share float_share free_share total_mv \\\n",
"0 1.0183 1.0183 26080.2350 18605.2851 14794.9501 2.040518e+06 \n",
"1 0.6398 0.6398 24721.2171 21036.5666 16807.4482 1.325304e+06 \n",
"2 0.0945 0.0945 102510.0438 102412.9669 64854.1551 1.084556e+06 \n",
"3 0.0665 0.0533 8594.7726 8400.0000 6014.9271 6.420123e+06 \n",
"4 NaN NaN 18421.3929 9389.9078 6414.2078 3.371115e+05 \n",
"... ... ... ... ... ... ... \n",
"27350 1.1303 1.1303 116144.2159 97496.2288 51416.3105 1.401861e+06 \n",
"27351 NaN NaN 42163.0000 12466.9576 12097.9576 5.843792e+05 \n",
"27352 1.7937 1.7937 32634.1682 31649.5307 12560.3926 3.707242e+05 \n",
"27353 NaN NaN 96649.4707 96600.7681 77600.7681 2.285760e+06 \n",
"27354 1.9711 2.0779 392444.2493 392354.1671 256620.6136 2.244781e+06 \n",
"\n",
" circ_mv is_st \n",
"0 1.504022e+06 False \n",
"1 9.960884e+05 False \n",
"2 5.667440e+05 False \n",
"3 1.236796e+06 False \n",
"4 2.008635e+05 False \n",
"0 1.455678e+06 False \n",
"1 1.127770e+06 False \n",
"2 1.083529e+06 False \n",
"3 6.274632e+06 False \n",
"4 1.718353e+05 False \n",
"... ... ... \n",
"27325 3.057724e+06 False \n",
"27326 5.782643e+05 False \n",
"27327 1.514190e+05 True \n",
"27328 1.006609e+08 False \n",
"27329 5.684393e+05 False \n",
"27350 1.176779e+06 False \n",
"27351 1.727920e+05 False \n",
"27352 3.595387e+05 False \n",
"27353 2.284608e+06 False \n",
"27354 2.244266e+06 False \n",
"\n",
"[27330 rows x 19 columns]\n"
"[27355 rows x 19 columns]\n"
]
}
],
@@ -311,45 +306,58 @@
"output_type": "stream",
"text": [
" ts_code trade_date close turnover_rate turnover_rate_f \\\n",
"52 002713.SZ 20260206 9.52 4.6530 6.2693 \n",
"107 000609.SZ 20260206 8.23 0.2427 0.3213 \n",
"113 300052.SZ 20260206 13.86 3.5983 4.3260 \n",
"116 600624.SH 20260206 5.31 0.6260 0.8827 \n",
"119 300555.SZ 20260206 14.31 1.4520 1.7474 \n",
"5 603261.SH 20260213 28.95 0.4664 1.3719 \n",
"14 002700.SZ 20260213 7.28 1.5973 1.6181 \n",
"34 300344.SZ 20260213 1.87 14.3407 25.9753 \n",
"67 000430.SZ 20260213 7.26 0.8541 1.3705 \n",
"81 000752.SZ 20260213 10.86 1.0429 1.2849 \n",
"... ... ... ... ... ... \n",
"27182 000668.SZ 20260202 13.85 3.5014 5.9253 \n",
"27240 003032.SZ 20260202 6.37 2.2066 3.1223 \n",
"27305 000691.SZ 20260202 8.30 1.9108 2.2317 \n",
"27312 300167.SZ 20260202 4.65 2.1705 2.3552 \n",
"27327 000004.SZ 20260202 11.99 0.2338 0.3161 \n",
"27165 300301.SZ 20260209 2.49 1.9012 2.0554 \n",
"27244 002822.SZ 20260209 3.53 1.0762 1.0762 \n",
"27270 300147.SZ 20260209 9.44 1.7053 2.2069 \n",
"27281 002501.SZ 20260209 2.16 3.6044 4.6543 \n",
"27297 002620.SZ 20260209 5.98 2.2406 3.1755 \n",
"\n",
" volume_ratio pe pe_ttm pb ps ps_ttm dv_ratio dv_ttm \\\n",
"52 1.02 NaN NaN NaN 6.9890 12.8336 NaN NaN \n",
"107 0.05 NaN NaN NaN 8.0655 15.8232 NaN NaN \n",
"113 1.51 NaN NaN 9.6004 15.9784 18.8191 NaN NaN \n",
"116 0.60 NaN NaN 5.7984 5.5900 5.4551 NaN NaN \n",
"119 1.24 NaN NaN 6.0224 16.1604 18.5602 NaN NaN \n",
"... ... .. ... ... ... ... ... ... \n",
"27182 1.32 NaN NaN 2.8792 15.2387 7.2708 NaN NaN \n",
"27240 1.15 NaN NaN 2.0451 10.4354 7.6772 NaN NaN \n",
"27305 0.69 NaN NaN NaN 9.0850 9.0002 NaN NaN \n",
"27312 0.71 NaN 134.128 63.0032 4.3517 3.8269 NaN NaN \n",
"27327 0.05 NaN NaN 42.9590 16.0879 21.5107 NaN NaN \n",
" volume_ratio pe pe_ttm pb ps ps_ttm dv_ratio \\\n",
"5 0.49 NaN NaN 3.3744 7.7410 7.8754 NaN \n",
"14 0.77 32.3153 40.4077 2.2014 4.2912 4.3540 0.9066 \n",
"34 0.60 NaN NaN 5.3118 4.6416 4.9881 NaN \n",
"67 0.49 NaN NaN 21.9522 13.6188 12.8340 NaN \n",
"81 1.21 109.3444 19.4711 4.6597 6.7963 6.4062 NaN \n",
"... ... ... ... ... ... ... ... \n",
"27165 0.97 NaN NaN 12.5588 4.0907 4.7109 NaN \n",
"27244 0.95 NaN NaN 4.9828 2.9693 6.5620 NaN \n",
"27270 1.21 NaN NaN 9.0126 3.3586 4.2436 NaN \n",
"27281 0.87 NaN NaN 29.0833 22.9884 26.1834 NaN \n",
"27297 1.30 NaN NaN NaN 2.8840 4.2972 NaN \n",
"\n",
" total_share float_share free_share total_mv circ_mv is_st \n",
"52 95140.5184 52650.0831 39075.6229 905737.7352 501228.7911 True \n",
"107 29926.5522 29105.8272 21991.3472 246295.5246 239540.9579 True \n",
"113 26185.8710 26185.1210 21780.6332 362936.1721 362925.7771 True \n",
"116 67934.6942 67934.6942 48180.1806 360733.2262 360733.2262 True \n",
"119 20000.0000 19798.4863 16450.7792 286200.0000 283316.3390 True \n",
"... ... ... ... ... ... ... \n",
"27182 14684.1890 14684.1890 8677.2104 203376.0177 203376.0177 True \n",
"27240 40244.7500 27621.9885 19520.7308 256359.0575 175952.0667 True \n",
"27305 48490.5000 32327.0000 27679.8405 402471.1500 268314.1000 True \n",
"27312 38937.4000 35889.3250 33073.6637 181058.9100 166885.3613 True \n",
"27327 13238.0282 12628.7768 9339.3580 158723.9581 151419.0338 True \n",
" dv_ttm total_share float_share free_share total_mv \\\n",
"5 NaN 7750.5022 7750.5022 2634.9858 224377.0387 \n",
"14 0.9066 41362.8185 26346.4874 26007.0037 301121.3187 \n",
"34 NaN 64170.6416 63999.4166 35333.5001 119999.0998 \n",
"67 NaN 80963.5372 37055.6486 23092.8156 587795.2801 \n",
"81 NaN 26375.8491 26375.8491 21407.3042 286441.7212 \n",
"... ... ... ... ... ... \n",
"27165 NaN 82986.8769 78987.6719 73061.8561 206637.3235 \n",
"27244 NaN 195094.2200 107059.0368 107059.0368 688682.5966 \n",
"27270 NaN 66127.9045 65739.8353 50798.8432 624247.4185 \n",
"27281 NaN 355000.0000 354646.9206 274646.9206 766800.0000 \n",
"27297 NaN 37749.4000 31536.0303 22251.3747 225741.4120 \n",
"\n",
"[872 rows x 19 columns]\n"
" circ_mv is_st \n",
"5 224377.0387 True \n",
"14 191802.4283 True \n",
"34 119678.9090 True \n",
"67 269024.0088 True \n",
"81 286441.7212 True \n",
"... ... ... \n",
"27165 196679.3030 True \n",
"27244 377918.3999 True \n",
"27270 620584.0452 True \n",
"27281 766037.3485 True \n",
"27297 188585.4612 True \n",
"\n",
"[870 rows x 19 columns]\n"
]
}
],
@@ -399,7 +407,7 @@
"output_type": "stream",
"text": [
"<class 'pandas.core.frame.DataFrame'>\n",
"Index: 9629640 entries, 0 to 27329\n",
"Index: 9656995 entries, 0 to 27354\n",
"Data columns (total 3 columns):\n",
" # Column Dtype \n",
"--- ------ ----- \n",
@@ -407,7 +415,7 @@
" 1 trade_date object\n",
" 2 is_st bool \n",
"dtypes: bool(1), object(2)\n",
"memory usage: 229.6+ MB\n",
"memory usage: 230.2+ MB\n",
"None\n"
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -34,17 +34,17 @@
"output_type": "stream",
"text": [
"<class 'pandas.core.frame.DataFrame'>\n",
"Index: 9387872 entries, 0 to 25863\n",
"Index: 9413748 entries, 0 to 25875\n",
"Data columns (total 2 columns):\n",
" # Column Dtype \n",
"--- ------ ----- \n",
" 0 ts_code object\n",
" 1 trade_date object\n",
"dtypes: object(2)\n",
"memory usage: 214.9+ MB\n",
"memory usage: 215.5+ MB\n",
"None\n",
"20260130\n",
"start_date: 20260202\n"
"20260206\n",
"start_date: 20260209\n"
]
}
],
@@ -99,12 +99,7 @@
"任务 20260212 完成\n",
"任务 20260211 完成\n",
"任务 20260210 完成\n",
"任务 20260209 完成\n",
"任务 20260206 完成\n",
"任务 20260205 完成\n",
"任务 20260204 完成\n",
"任务 20260203 完成\n",
"任务 20260202 完成\n"
"任务 20260209 完成\n"
]
}
],
@@ -194,71 +189,71 @@
"output_type": "stream",
"text": [
" ts_code trade_date buy_sm_vol buy_sm_amount sell_sm_vol \\\n",
"0 002397.SZ 20260206 143016 6566.04 142640 \n",
"1 603882.SH 20260206 32234 10009.25 31819 \n",
"2 002824.SZ 20260206 58407 13856.33 47164 \n",
"3 603379.SH 20260206 31545 21744.99 30955 \n",
"4 600223.SH 20260206 73778 5582.50 67552 \n",
"0 300587.SZ 20260213 154110 9661.44 160598 \n",
"1 601000.SH 20260213 150959 6301.54 197344 \n",
"2 002338.SZ 20260213 9215 5012.78 8260 \n",
"3 688373.SH 20260213 29166 1845.78 30329 \n",
"4 002226.SZ 20260213 101435 6137.98 79302 \n",
"... ... ... ... ... ... \n",
"25871 002774.SZ 20260202 32854 3675.61 20566 \n",
"25872 300188.SZ 20260202 54005 7416.58 48176 \n",
"25873 688173.SH 20260202 64149 10373.20 68049 \n",
"25874 300145.SZ 20260202 132990 6043.37 133529 \n",
"25875 300205.SZ 20260202 8361 364.75 6236 \n",
"25887 603713.SH 20260209 9898 6481.74 10208 \n",
"25888 300004.SZ 20260209 41923 5934.14 50255 \n",
"25889 300975.SZ 20260209 198244 30367.70 159191 \n",
"25890 603381.SH 20260209 85934 22581.16 95505 \n",
"25891 002836.SZ 20260209 27160 4238.25 22047 \n",
"\n",
" sell_sm_amount buy_md_vol buy_md_amount sell_md_vol sell_md_amount \\\n",
"0 6550.08 114346 5247.29 121777 5580.76 \n",
"1 9880.13 15560 4828.56 14519 4506.56 \n",
"2 11195.49 27988 6622.95 30015 7118.27 \n",
"3 21323.49 21708 14968.66 21044 14503.09 \n",
"4 5110.61 53914 4075.02 53354 4037.48 \n",
"0 10061.76 183752 11498.51 186971 11701.15 \n",
"1 8233.85 84549 3527.41 71932 3003.18 \n",
"2 4495.09 9488 5163.47 9035 4920.33 \n",
"3 1918.49 10043 635.49 10005 633.64 \n",
"4 4796.49 104000 6296.98 78239 4741.21 \n",
"... ... ... ... ... ... \n",
"25871 2300.99 20761 2320.61 21785 2437.00 \n",
"25872 6623.07 52821 7250.13 53449 7347.52 \n",
"25873 11000.03 35320 5706.28 30270 4895.56 \n",
"25874 6066.65 114646 5208.71 97260 4422.03 \n",
"25875 272.25 9374 408.60 9827 427.93 \n",
"25887 6683.01 6735 4413.49 7402 4854.70 \n",
"25888 7133.88 53004 7510.03 58384 8274.31 \n",
"25889 24423.94 164520 25222.01 193044 29612.42 \n",
"25890 25109.67 65977 17316.88 71008 18669.88 \n",
"25891 3438.16 21123 3293.94 20955 3271.07 \n",
"\n",
" buy_lg_vol buy_lg_amount sell_lg_vol sell_lg_amount buy_elg_vol \\\n",
"0 85477 3926.44 87204 3989.37 28400 \n",
"1 5474 1697.68 6390 1982.08 721 \n",
"2 11723 2778.17 15330 3630.71 3939 \n",
"3 13069 9000.74 15789 10882.14 7583 \n",
"4 27279 2062.59 22583 1709.48 10118 \n",
"0 139274 8711.00 168037 10519.91 60907 \n",
"1 57471 2398.28 37552 1567.23 21177 \n",
"2 5873 3195.64 5312 2890.59 514 \n",
"3 8238 521.88 7113 451.02 0 \n",
"4 50394 3048.72 69021 4177.39 9335 \n",
"... ... ... ... ... ... \n",
"25871 8975 1002.99 18793 2100.36 0 \n",
"25872 31050 4271.36 35903 4923.97 7655 \n",
"25873 11829 1915.52 12687 2050.68 2000 \n",
"25874 81164 3682.66 113414 5149.25 41421 \n",
"25875 6887 302.35 8559 375.51 0 \n",
"25887 3515 2307.87 4056 2660.17 2867 \n",
"25888 49767 7060.10 39566 5596.12 8820 \n",
"25889 116306 17856.14 144536 22152.02 51550 \n",
"25890 46270 12156.66 38176 10028.63 11944 \n",
"25891 9676 1508.43 11383 1772.18 1000 \n",
"\n",
" buy_elg_amount sell_elg_vol sell_elg_amount net_mf_vol \\\n",
"0 1293.83 19618 913.39 42201 \n",
"1 223.34 1261 390.07 -823 \n",
"2 935.53 9548 2248.51 2997 \n",
"3 5221.72 6117 4227.39 6215 \n",
"4 766.07 21600 1628.62 -9839 \n",
"0 3816.45 22437 1404.58 142435 \n",
"1 882.70 7328 305.66 -48700 \n",
"2 280.52 2483 1346.40 -483 \n",
"3 0.00 0 0.00 982 \n",
"4 565.27 38602 2333.86 -103058 \n",
"... ... ... ... ... \n",
"25871 0.00 1446 160.86 -20182 \n",
"25872 1053.35 8003 1096.85 -12903 \n",
"25873 319.00 2291 367.73 -5670 \n",
"25874 1881.32 26018 1178.15 -70082 \n",
"25875 0.00 0 0.00 -1678 \n",
"25887 1885.53 1349 890.75 1237 \n",
"25888 1251.47 5309 751.42 8180 \n",
"25889 7924.73 33850 5182.21 -41375 \n",
"25890 3157.32 5436 1403.84 -11696 \n",
"25891 155.40 4574 714.61 1257 \n",
"\n",
" net_mf_amount \n",
"0 1943.09 \n",
"1 -246.33 \n",
"2 705.13 \n",
"3 4367.94 \n",
"4 -741.40 \n",
"0 8918.59 \n",
"1 -2025.73 \n",
"2 -250.58 \n",
"3 64.60 \n",
"4 -6231.26 \n",
"... ... \n",
"25871 -2251.19 \n",
"25872 -1769.73 \n",
"25873 -918.58 \n",
"25874 -3146.31 \n",
"25875 -68.42 \n",
"25887 814.61 \n",
"25888 1173.63 \n",
"25889 -6267.77 \n",
"25890 -3055.51 \n",
"25891 191.86 \n",
"\n",
"[25876 rows x 20 columns]\n"
"[25892 rows x 20 columns]\n"
]
}
],
@@ -283,7 +278,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.11"
"version": "3.13.2"
}
},
"nbformat": 4,

View File

@@ -34,23 +34,23 @@
"output_type": "stream",
"text": [
" ts_code trade_date\n",
"4971 600208.SH 20260130\n",
"4972 600210.SH 20260130\n",
"4973 600211.SH 20260130\n",
"4961 600195.SH 20260130\n",
"7441 920964.BJ 20260130\n",
"4979 600202.SH 20260206\n",
"4980 600203.SH 20260206\n",
"4981 600206.SH 20260206\n",
"4969 600189.SH 20260206\n",
"7454 920964.BJ 20260206\n",
"<class 'pandas.core.frame.DataFrame'>\n",
"Index: 11775527 entries, 0 to 37233\n",
"Index: 11812821 entries, 0 to 37293\n",
"Data columns (total 2 columns):\n",
" # Column Dtype \n",
"--- ------ ----- \n",
" 0 ts_code object\n",
" 1 trade_date object\n",
"dtypes: object(2)\n",
"memory usage: 269.5+ MB\n",
"memory usage: 270.4+ MB\n",
"None\n",
"20260130\n",
"20260202\n"
"20260206\n",
"20260209\n"
]
}
],
@@ -95,8 +95,8 @@
"任务 20260309 完成\n",
"任务 20260306 完成\n",
"任务 20260305 完成\n",
"任务 20260303 完成\n",
"任务 20260304 完成\n",
"任务 20260303 完成\n",
"任务 20260302 完成\n",
"任务 20260227 完成\n",
"任务 20260226 完成\n",
@@ -106,12 +106,7 @@
"任务 20260212 完成\n",
"任务 20260211 完成\n",
"任务 20260210 完成\n",
"任务 20260209 完成\n",
"任务 20260206 完成\n",
"任务 20260205 完成\n",
"任务 20260204 完成\n",
"任务 20260203 完成\n",
"任务 20260202 完成\n"
"任务 20260209 完成\n"
]
}
],
@@ -163,71 +158,71 @@
"output_type": "stream",
"text": [
"[ trade_date ts_code up_limit down_limit\n",
"0 20260206 000001.SZ 12.20 9.98\n",
"1 20260206 000002.SZ 5.37 4.39\n",
"2 20260206 000004.SZ 10.79 9.77\n",
"3 20260206 000006.SZ 9.90 8.10\n",
"4 20260206 000007.SZ 12.31 10.07\n",
"0 20260213 000001.SZ 12.06 9.86\n",
"1 20260213 000002.SZ 5.41 4.43\n",
"2 20260213 000004.SZ 8.36 7.56\n",
"3 20260213 000006.SZ 10.12 8.28\n",
"4 20260213 000007.SZ 13.44 11.00\n",
"... ... ... ... ...\n",
"7459 20260206 920978.BJ 41.60 22.40\n",
"7460 20260206 920981.BJ 41.63 22.43\n",
"7461 20260206 920982.BJ 298.63 160.81\n",
"7462 20260206 920985.BJ 11.37 6.13\n",
"7463 20260206 920992.BJ 22.32 12.02\n",
"7476 20260213 920978.BJ 39.09 21.05\n",
"7477 20260213 920981.BJ 41.61 22.41\n",
"7478 20260213 920982.BJ 284.06 152.96\n",
"7479 20260213 920985.BJ 11.34 6.12\n",
"7480 20260213 920992.BJ 21.77 11.73\n",
"\n",
"[7464 rows x 4 columns], trade_date ts_code up_limit down_limit\n",
"0 20260205 000001.SZ 12.07 9.87\n",
"1 20260205 000002.SZ 5.39 4.41\n",
"2 20260205 000004.SZ 11.36 10.28\n",
"3 20260205 000006.SZ 9.97 8.15\n",
"4 20260205 000007.SZ 12.32 10.08\n",
"[7481 rows x 4 columns], trade_date ts_code up_limit down_limit\n",
"0 20260212 000001.SZ 12.18 9.96\n",
"1 20260212 000002.SZ 5.38 4.40\n",
"2 20260212 000004.SZ 8.80 7.96\n",
"3 20260212 000006.SZ 10.29 8.42\n",
"4 20260212 000007.SZ 13.31 10.89\n",
"... ... ... ... ...\n",
"7454 20260205 920978.BJ 41.48 22.34\n",
"7455 20260205 920981.BJ 42.00 22.62\n",
"7456 20260205 920982.BJ 289.43 155.85\n",
"7457 20260205 920985.BJ 12.16 6.56\n",
"7458 20260205 920992.BJ 22.32 12.02\n",
"7476 20260212 920978.BJ 39.93 21.51\n",
"7477 20260212 920981.BJ 41.60 22.40\n",
"7478 20260212 920982.BJ 284.29 153.09\n",
"7479 20260212 920985.BJ 11.01 5.93\n",
"7480 20260212 920992.BJ 21.86 11.78\n",
"\n",
"[7459 rows x 4 columns], trade_date ts_code up_limit down_limit\n",
"0 20260204 000001.SZ 11.92 9.76\n",
"1 20260204 000002.SZ 5.17 4.23\n",
"2 20260204 000004.SZ 11.96 10.82\n",
"3 20260204 000006.SZ 9.77 7.99\n",
"4 20260204 000007.SZ 12.32 10.08\n",
"[7481 rows x 4 columns], trade_date ts_code up_limit down_limit\n",
"0 20260211 000001.SZ 12.17 9.95\n",
"1 20260211 000002.SZ 5.37 4.39\n",
"2 20260211 000004.SZ 9.26 8.38\n",
"3 20260211 000006.SZ 10.18 8.33\n",
"4 20260211 000007.SZ 13.37 10.94\n",
"... ... ... ... ...\n",
"7453 20260204 920978.BJ 38.15 20.55\n",
"7454 20260204 920981.BJ 43.01 23.17\n",
"7455 20260204 920982.BJ 279.50 150.50\n",
"7456 20260204 920985.BJ 10.66 5.74\n",
"7457 20260204 920992.BJ 22.28 12.00\n",
"7469 20260211 920978.BJ 41.02 22.10\n",
"7470 20260211 920981.BJ 41.91 22.57\n",
"7471 20260211 920982.BJ 286.35 154.19\n",
"7472 20260211 920985.BJ 11.34 6.12\n",
"7473 20260211 920992.BJ 22.04 11.88\n",
"\n",
"[7458 rows x 4 columns], trade_date ts_code up_limit down_limit\n",
"0 20260203 000001.SZ 11.95 9.77\n",
"1 20260203 000002.SZ 5.15 4.21\n",
"2 20260203 000004.SZ 12.59 11.39\n",
"3 20260203 000006.SZ 9.58 7.84\n",
"4 20260203 000007.SZ 12.09 9.89\n",
"[7474 rows x 4 columns], trade_date ts_code up_limit down_limit\n",
"0 20260210 000001.SZ 12.18 9.96\n",
"1 20260210 000002.SZ 5.46 4.46\n",
"2 20260210 000004.SZ 9.74 8.82\n",
"3 20260210 000006.SZ 10.32 8.44\n",
"4 20260210 000007.SZ 13.53 11.07\n",
"... ... ... ... ...\n",
"7453 20260203 920978.BJ 37.93 20.43\n",
"7454 20260203 920981.BJ 42.52 22.90\n",
"7455 20260203 920982.BJ 279.35 150.43\n",
"7456 20260203 920985.BJ 10.15 5.47\n",
"7457 20260203 920992.BJ 21.95 11.83\n",
"7466 20260210 920978.BJ 41.71 22.47\n",
"7467 20260210 920981.BJ 42.05 22.65\n",
"7468 20260210 920982.BJ 289.90 156.10\n",
"7469 20260210 920985.BJ 11.83 6.37\n",
"7470 20260210 920992.BJ 22.33 12.03\n",
"\n",
"[7458 rows x 4 columns], trade_date ts_code up_limit down_limit\n",
"0 20260202 000001.SZ 11.91 9.75\n",
"1 20260202 000002.SZ 5.37 4.39\n",
"2 20260202 000004.SZ 13.25 11.99\n",
"3 20260202 000006.SZ 9.86 8.06\n",
"4 20260202 000007.SZ 11.97 9.79\n",
"[7471 rows x 4 columns], trade_date ts_code up_limit down_limit\n",
"0 20260209 000001.SZ 12.16 9.95\n",
"1 20260209 000002.SZ 5.29 4.33\n",
"2 20260209 000004.SZ 10.26 9.28\n",
"3 20260209 000006.SZ 9.88 8.08\n",
"4 20260209 000007.SZ 13.00 10.64\n",
"... ... ... ... ...\n",
"7450 20260202 920978.BJ 40.36 21.74\n",
"7451 20260202 920981.BJ 45.50 24.50\n",
"7452 20260202 920982.BJ 287.80 154.98\n",
"7453 20260202 920985.BJ 10.33 5.57\n",
"7454 20260202 920992.BJ 22.63 12.19\n",
"7462 20260209 920978.BJ 42.45 22.87\n",
"7463 20260209 920981.BJ 41.40 22.30\n",
"7464 20260209 920982.BJ 291.70 157.08\n",
"7465 20260209 920985.BJ 11.32 6.10\n",
"7466 20260209 920992.BJ 22.13 11.93\n",
"\n",
"[7455 rows x 4 columns]]\n"
"[7467 rows x 4 columns]]\n"
]
}
],
@@ -295,7 +290,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.11"
"version": "3.13.2"
}
},
"nbformat": 4,

View File

@@ -78,7 +78,7 @@
"cyq perf\n",
"left merge on ['ts_code', 'trade_date']\n",
"<class 'pandas.core.frame.DataFrame'>\n",
"RangeIndex: 9410807 entries, 0 to 9410806\n",
"RangeIndex: 9436343 entries, 0 to 9436342\n",
"Data columns (total 33 columns):\n",
" # Column Dtype \n",
"--- ------ ----- \n",
@@ -446,21 +446,21 @@
"fina_indicator_df = read_and_merge_h5_data('/mnt/d/PyProject/NewStock/data/fina_indicator.h5', key='fina_indicator',\n",
" columns=['ts_code', 'ann_date', 'undist_profit_ps', 'ocfps', 'bps', 'roa', 'roe'],\n",
" df=None)\n",
"cashflow_df = read_and_merge_h5_data('/mnt/d/PyProject/NewStock/data/cashflow.h5', key='cashflow',\n",
" columns=['ts_code', 'ann_date', 'n_cashflow_act'],\n",
" df=None)\n",
"balancesheet_df = read_and_merge_h5_data('/mnt/d/PyProject/NewStock/data/balancesheet.h5', key='balancesheet',\n",
" columns=['ts_code', 'ann_date', 'money_cap', 'total_liab'],\n",
" df=None)\n",
"top_list_df = read_and_merge_h5_data('/mnt/d/PyProject/NewStock/data/top_list.h5', key='top_list',\n",
" columns=['ts_code', 'trade_date', 'reason'],\n",
" df=None)\n",
"# cashflow_df = read_and_merge_h5_data('/mnt/d/PyProject/NewStock/data/cashflow.h5', key='cashflow',\n",
"# columns=['ts_code', 'ann_date', 'n_cashflow_act'],\n",
"# df=None)\n",
"# balancesheet_df = read_and_merge_h5_data('/mnt/d/PyProject/NewStock/data/balancesheet.h5', key='balancesheet',\n",
"# columns=['ts_code', 'ann_date', 'money_cap', 'total_liab'],\n",
"# df=None)\n",
"# top_list_df = read_and_merge_h5_data('/mnt/d/PyProject/NewStock/data/top_list.h5', key='top_list',\n",
"# columns=['ts_code', 'trade_date', 'reason'],\n",
"# df=None)\n",
"\n",
"top_list_df = top_list_df.sort_values(by='trade_date', ascending=False).drop_duplicates(subset=['ts_code', 'trade_date'], keep='first').sort_values(by='trade_date')\n",
"# top_list_df = top_list_df.sort_values(by='trade_date', ascending=False).drop_duplicates(subset=['ts_code', 'trade_date'], keep='first').sort_values(by='trade_date')\n",
"\n",
"stk_holdertrade_df = read_and_merge_h5_data('/mnt/d/PyProject/NewStock/data/stk_holdertrade.h5', key='stk_holdertrade',\n",
" columns=['ts_code', 'ann_date', 'in_de', 'change_ratio', 'after_ratio'],\n",
" df=None)"
"# stk_holdertrade_df = read_and_merge_h5_data('/mnt/d/PyProject/NewStock/data/stk_holdertrade.h5', key='stk_holdertrade',\n",
"# columns=['ts_code', 'ann_date', 'in_de', 'change_ratio', 'after_ratio'],\n",
"# df=None)"
]
},
{
@@ -479,133 +479,27 @@
"output_type": "stream",
"text": [
"使用 'ann_date' 作为财务数据生效日期。\n",
"警告: 从 financial_data_subset 中移除了 366 行,因为其 'ts_code' 或 'ann_date' 列存在空值。\n",
"警告: 从 financial_data_subset 中移除了 15 行,因为其 'ts_code' 或 'ann_date' 列存在空值。\n",
"使用 'ann_date' 作为财务数据生效日期。\n",
"警告: 从 financial_data_subset 中移除了 366 行,因为其 'ts_code' 或 'ann_date' 列存在空值。\n",
"警告: 从 financial_data_subset 中移除了 15 行,因为其 'ts_code' 或 'ann_date' 列存在空值。\n",
"使用 'ann_date' 作为财务数据生效日期。\n",
"警告: 从 financial_data_subset 中移除了 366 行,因为其 'ts_code' 或 'ann_date' 列存在空值。\n",
"警告: 从 financial_data_subset 中移除了 15 行,因为其 'ts_code' 或 'ann_date' 列存在空值。\n",
"使用 'ann_date' 作为财务数据生效日期。\n",
"警告: 从 financial_data_subset 中移除了 366 行,因为其 'ts_code' 或 'ann_date' 列存在空值。\n",
"警告: 从 financial_data_subset 中移除了 15 行,因为其 'ts_code' 或 'ann_date' 列存在空值。\n",
"开始计算因子: AR, BR (原地修改)...\n",
"因子 AR, BR 计算成功。\n",
"因子 AR, BR 计算流程结束。\n",
"使用 'ann_date' 作为财务数据生效日期。\n",
"使用 'ann_date' 作为财务数据生效日期。\n",
"使用 'ann_date' 作为财务数据生效日期。\n",
"使用 'ann_date' 作为财务数据生效日期。\n",
"警告: 从 financial_data_subset 中移除了 366 行,因为其 'ts_code' 或 'ann_date' 列存在空值。\n",
"计算 BBI...\n",
"--- 计算日级别偏离度 (使用 pct_chg) ---\n",
"--- 计算日级别动量基准 (使用 pct_chg) ---\n",
"日级别动量基准计算完成 (使用 pct_chg)。\n",
"日级别偏离度计算完成 (使用 pct_chg)。\n",
"--- 计算日级别行业偏离度 (使用 pct_chg 和行业基准) ---\n",
"--- 计算日级别行业动量基准 (使用 pct_chg 和 cat_l2_code) ---\n",
"错误: 计算日级别行业动量基准需要以下列: ['pct_chg', 'cat_l2_code', 'trade_date', 'ts_code']。\n",
"错误: 计算日级别行业偏离度需要以下列: ['pct_chg', 'daily_industry_positive_benchmark', 'daily_industry_negative_benchmark']。请先运行 daily_industry_momentum_benchmark(df)。\n",
"Index(['ts_code', 'trade_date', 'open', 'close', 'high', 'low', 'vol',\n",
" 'amount', 'pct_chg', 'turnover_rate', 'pe_ttm', 'circ_mv', 'total_mv',\n",
" 'volume_ratio', 'is_st', 'up_limit', 'down_limit', 'buy_sm_vol',\n",
" 'sell_sm_vol', 'buy_lg_vol', 'sell_lg_vol', 'buy_elg_vol',\n",
" 'sell_elg_vol', 'net_mf_vol', 'his_low', 'his_high', 'cost_5pct',\n",
" 'cost_15pct', 'cost_50pct', 'cost_85pct', 'cost_95pct', 'weight_avg',\n",
" 'winner_rate', 'l2_code', 'undist_profit_ps', 'ocfps', 'roa', 'roe',\n",
" 'AR', 'BR', 'AR_BR', 'log_circ_mv', 'cashflow_to_ev_factor',\n",
" 'book_to_price_ratio', 'turnover_rate_mean_5', 'variance_20',\n",
" 'bbi_ratio_factor', 'daily_deviation', 'lg_elg_net_buy_vol',\n",
" 'flow_lg_elg_intensity', 'sm_net_buy_vol', 'flow_divergence_diff',\n",
" 'flow_divergence_ratio', 'total_buy_vol', 'lg_elg_buy_prop',\n",
" 'flow_struct_buy_change', 'lg_elg_net_buy_vol_change',\n",
" 'flow_lg_elg_accel', 'chip_concentration_range', 'chip_skewness',\n",
" 'floating_chip_proxy', 'cost_support_15pct_change',\n",
" 'cat_winner_price_zone', 'flow_chip_consistency',\n",
" 'profit_taking_vs_absorb', '_is_positive', '_is_negative',\n",
" 'cat_is_positive', '_pos_returns', '_neg_returns', '_pos_returns_sq',\n",
" '_neg_returns_sq', 'upside_vol', 'downside_vol', 'vol_ratio',\n",
" 'return_skew', 'return_kurtosis', 'volume_change_rate',\n",
" 'cat_volume_breakout', 'turnover_deviation', 'cat_turnover_spike',\n",
" 'avg_volume_ratio', 'cat_volume_ratio_breakout', 'vol_spike',\n",
" 'vol_std_5', 'atr_14', 'atr_6', 'obv'],\n",
" dtype='object')\n",
"Calculating lg_flow_mom_corr_20_60...\n",
"Finished lg_flow_mom_corr_20_60.\n",
"Calculating lg_flow_accel...\n",
"Finished lg_flow_accel.\n",
"Calculating profit_pressure...\n",
"Finished profit_pressure.\n",
"Calculating underwater_resistance...\n",
"Finished underwater_resistance.\n",
"Calculating cost_conc_std_20...\n",
"Finished cost_conc_std_20.\n",
"Calculating profit_decay_20...\n",
"Finished profit_decay_20.\n",
"Calculating vol_amp_loss_20...\n",
"Finished vol_amp_loss_20.\n",
"Calculating vol_drop_profit_cnt_5...\n",
"Finished vol_drop_profit_cnt_5.\n",
"Calculating lg_flow_vol_interact_20...\n",
"Finished lg_flow_vol_interact_20.\n",
"Calculating cost_break_confirm_cnt_5...\n",
"Finished cost_break_confirm_cnt_5.\n",
"Calculating atr_norm_channel_pos_14...\n",
"Finished atr_norm_channel_pos_14.\n",
"Calculating turnover_diff_skew_20...\n",
"Finished turnover_diff_skew_20.\n",
"Calculating lg_sm_flow_diverge_20...\n",
"Finished lg_sm_flow_diverge_20.\n",
"Calculating pullback_strong_20_20...\n",
"Finished pullback_strong_20_20.\n",
"Calculating vol_wgt_hist_pos_20...\n",
"Finished vol_wgt_hist_pos_20.\n",
"Calculating vol_adj_roc_20...\n",
"Finished vol_adj_roc_20.\n",
"Calculating cs_rank_net_lg_flow_val...\n",
"Finished cs_rank_net_lg_flow_val.\n",
"Calculating cs_rank_flow_divergence...\n",
"Finished cs_rank_flow_divergence.\n",
"Calculating cs_rank_ind_adj_lg_flow...\n",
"Finished cs_rank_ind_adj_lg_flow.\n",
"Calculating cs_rank_elg_buy_ratio...\n",
"Finished cs_rank_elg_buy_ratio.\n",
"Calculating cs_rank_rel_profit_margin...\n",
"Finished cs_rank_rel_profit_margin.\n",
"Calculating cs_rank_cost_breadth...\n",
"Finished cs_rank_cost_breadth.\n",
"Calculating cs_rank_dist_to_upper_cost...\n",
"Finished cs_rank_dist_to_upper_cost.\n",
"Calculating cs_rank_winner_rate...\n",
"Finished cs_rank_winner_rate.\n",
"Calculating cs_rank_intraday_range...\n",
"Finished cs_rank_intraday_range.\n",
"Calculating cs_rank_close_pos_in_range...\n",
"Finished cs_rank_close_pos_in_range.\n",
"Calculating cs_rank_opening_gap...\n",
"Error calculating cs_rank_opening_gap: Missing 'pre_close' column. Assigning NaN.\n",
"Calculating cs_rank_pos_in_hist_range...\n",
"Finished cs_rank_pos_in_hist_range.\n",
"Calculating cs_rank_vol_x_profit_margin...\n",
"Finished cs_rank_vol_x_profit_margin.\n",
"Calculating cs_rank_lg_flow_price_concordance...\n",
"Finished cs_rank_lg_flow_price_concordance.\n",
"Calculating cs_rank_turnover_per_winner...\n",
"Finished cs_rank_turnover_per_winner.\n",
"Calculating cs_rank_ind_cap_neutral_pe (Placeholder - requires statsmodels)...\n",
"Finished cs_rank_ind_cap_neutral_pe (Placeholder).\n",
"Calculating cs_rank_volume_ratio...\n",
"Finished cs_rank_volume_ratio.\n",
"Calculating cs_rank_elg_buy_sell_sm_ratio...\n",
"Finished cs_rank_elg_buy_sell_sm_ratio.\n",
"Calculating cs_rank_cost_dist_vol_ratio...\n",
"Finished cs_rank_cost_dist_vol_ratio.\n",
"Calculating cs_rank_size...\n",
"Finished cs_rank_size.\n",
"<class 'pandas.core.frame.DataFrame'>\n",
"RangeIndex: 5072276 entries, 0 to 5072275\n",
"Columns: 181 entries, ts_code to cs_rank_size\n",
"dtypes: bool(10), datetime64[ns](1), float64(165), int64(3), object(2)\n",
"memory usage: 6.5+ GB\n",
"None\n",
"['ts_code', 'trade_date', 'open', 'close', 'high', 'low', 'vol', 'amount', 'pct_chg', 'turnover_rate', 'pe_ttm', 'circ_mv', 'total_mv', 'volume_ratio', 'is_st', 'up_limit', 'down_limit', 'buy_sm_vol', 'sell_sm_vol', 'buy_lg_vol', 'sell_lg_vol', 'buy_elg_vol', 'sell_elg_vol', 'net_mf_vol', 'his_low', 'his_high', 'cost_5pct', 'cost_15pct', 'cost_50pct', 'cost_85pct', 'cost_95pct', 'weight_avg', 'winner_rate', 'cat_l2_code', 'undist_profit_ps', 'ocfps', 'roa', 'roe', 'AR', 'BR', 'AR_BR', 'log_circ_mv', 'cashflow_to_ev_factor', 'book_to_price_ratio', 'turnover_rate_mean_5', 'variance_20', 'bbi_ratio_factor', 'daily_deviation', 'lg_elg_net_buy_vol', 'flow_lg_elg_intensity', 'sm_net_buy_vol', 'flow_divergence_diff', 'flow_divergence_ratio', 'total_buy_vol', 'lg_elg_buy_prop', 'flow_struct_buy_change', 'lg_elg_net_buy_vol_change', 'flow_lg_elg_accel', 'chip_concentration_range', 'chip_skewness', 'floating_chip_proxy', 'cost_support_15pct_change', 'cat_winner_price_zone', 'flow_chip_consistency', 'profit_taking_vs_absorb', 'cat_is_positive', 'upside_vol', 'downside_vol', 'vol_ratio', 'return_skew', 'return_kurtosis', 'volume_change_rate', 'cat_volume_breakout', 'turnover_deviation', 'cat_turnover_spike', 'avg_volume_ratio', 'cat_volume_ratio_breakout', 'vol_spike', 'vol_std_5', 'atr_14', 'atr_6', 'obv', 'maobv_6', 'rsi_3', 'return_5', 'return_20', 'std_return_5', 'std_return_90', 'std_return_90_2', 'act_factor1', 'act_factor2', 'act_factor3', 'act_factor4', 'rank_act_factor1', 'rank_act_factor2', 'rank_act_factor3', 'cov', 'delta_cov', 'alpha_22_improved', 'alpha_003', 'alpha_007', 'alpha_013', 'vol_break', 'weight_roc5', 'price_cost_divergence', 'smallcap_concentration', 'cost_stability', 'high_cost_break_days', 'liquidity_risk', 'turnover_std', 'mv_volatility', 'volume_growth', 'mv_growth', 'momentum_factor', 'resonance_factor', 'log_close', 'cat_vol_spike', 'up', 'down', 'obv_maobv_6', 'std_return_5_over_std_return_90', 'std_return_90_minus_std_return_90_2', 'cat_af2', 'cat_af3', 'cat_af4', 'act_factor5', 'act_factor6', 'active_buy_volume_large', 'active_buy_volume_big', 'active_buy_volume_small', 'buy_lg_vol_minus_sell_lg_vol', 'buy_elg_vol_minus_sell_elg_vol', 'ctrl_strength', 'low_cost_dev', 'asymmetry', 'lock_factor', 'cat_vol_break', 'cost_atr_adj', 'cat_golden_resonance', 'mv_turnover_ratio', 'mv_adjusted_volume', 'mv_weighted_turnover', 'nonlinear_mv_volume', 'mv_volume_ratio', 'mv_momentum', 'lg_flow_mom_corr_20_60', 'lg_flow_accel', 'profit_pressure', 'underwater_resistance', 'cost_conc_std_20', 'profit_decay_20', 'vol_amp_loss_20', 'vol_drop_profit_cnt_5', 'lg_flow_vol_interact_20', 'cost_break_confirm_cnt_5', 'atr_norm_channel_pos_14', 'turnover_diff_skew_20', 'lg_sm_flow_diverge_20', 'pullback_strong_20_20', 'vol_wgt_hist_pos_20', 'vol_adj_roc_20', 'cs_rank_net_lg_flow_val', 'cs_rank_flow_divergence', 'cs_rank_ind_adj_lg_flow', 'cs_rank_elg_buy_ratio', 'cs_rank_rel_profit_margin', 'cs_rank_cost_breadth', 'cs_rank_dist_to_upper_cost', 'cs_rank_winner_rate', 'cs_rank_intraday_range', 'cs_rank_close_pos_in_range', 'cs_rank_opening_gap', 'cs_rank_pos_in_hist_range', 'cs_rank_vol_x_profit_margin', 'cs_rank_lg_flow_price_concordance', 'cs_rank_turnover_per_winner', 'cs_rank_ind_cap_neutral_pe', 'cs_rank_volume_ratio', 'cs_rank_elg_buy_sell_sm_ratio', 'cs_rank_cost_dist_vol_ratio', 'cs_rank_size']\n"
"因子 AR, BR 计算流程结束。\n"
]
},
{
"ename": "NameError",
"evalue": "name 'cashflow_df' is not defined",
"output_type": "error",
"traceback": [
"\u001b[31m---------------------------------------------------------------------------\u001b[39m",
"\u001b[31mNameError\u001b[39m Traceback (most recent call last)",
"\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[10]\u001b[39m\u001b[32m, line 43\u001b[39m\n\u001b[32m 41\u001b[39m calculate_arbr(df, N=\u001b[32m26\u001b[39m)\n\u001b[32m 42\u001b[39m df[\u001b[33m'\u001b[39m\u001b[33mlog_circ_mv\u001b[39m\u001b[33m'\u001b[39m] = np.log(df[\u001b[33m'\u001b[39m\u001b[33mcirc_mv\u001b[39m\u001b[33m'\u001b[39m])\n\u001b[32m---> \u001b[39m\u001b[32m43\u001b[39m df = calculate_cashflow_to_ev_factor(df, \u001b[43mcashflow_df\u001b[49m, balancesheet_df)\n\u001b[32m 44\u001b[39m df = caculate_book_to_price_ratio(df, fina_indicator_df)\n\u001b[32m 46\u001b[39m df = turnover_rate_n(df, n=\u001b[32m5\u001b[39m)\n",
"\u001b[31mNameError\u001b[39m: name 'cashflow_df' is not defined"
]
}
],
@@ -714,7 +608,7 @@
},
{
"cell_type": "code",
"execution_count": 11,
"execution_count": null,
"id": "b87b938028afa206",
"metadata": {
"ExecuteTime": {
@@ -752,7 +646,7 @@
},
{
"cell_type": "code",
"execution_count": 12,
"execution_count": null,
"id": "f4f16d63ad18d1bc",
"metadata": {
"ExecuteTime": {
@@ -978,7 +872,7 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": null,
"id": "40e6b68a91b30c79",
"metadata": {
"ExecuteTime": {
@@ -1298,7 +1192,7 @@
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": null,
"id": "47c12bb34062ae7a",
"metadata": {
"ExecuteTime": {
@@ -1332,7 +1226,7 @@
},
{
"cell_type": "code",
"execution_count": 15,
"execution_count": null,
"id": "29221dde",
"metadata": {},
"outputs": [
@@ -1375,7 +1269,7 @@
},
{
"cell_type": "code",
"execution_count": 16,
"execution_count": null,
"id": "03ee5daf",
"metadata": {},
"outputs": [],
@@ -1388,7 +1282,7 @@
},
{
"cell_type": "code",
"execution_count": 17,
"execution_count": null,
"id": "b76ea08a",
"metadata": {},
"outputs": [
@@ -1396,10 +1290,10 @@
"name": "stdout",
"output_type": "stream",
"text": [
" ts_code trade_date log_circ_mv\n",
"0 000001.SZ 2019-01-02 16.574219\n",
"1 000001.SZ 2019-01-03 16.583965\n",
"2 000001.SZ 2019-01-04 16.633371\n",
" ts_code trade_date log_circ_mv\n",
"5087381 605599.SH 2026-02-11 14.480487\n",
"5087382 605599.SH 2026-02-12 14.482485\n",
"5087383 605599.SH 2026-02-13 14.493206\n",
"['vol', 'pct_chg', 'turnover_rate', 'volume_ratio', 'winner_rate', 'undist_profit_ps', 'ocfps', 'AR', 'BR', 'AR_BR', 'cashflow_to_ev_factor', 'book_to_price_ratio', 'turnover_rate_mean_5', 'variance_20', 'bbi_ratio_factor', 'daily_deviation', 'lg_elg_net_buy_vol', 'flow_lg_elg_intensity', 'sm_net_buy_vol', 'total_buy_vol', 'lg_elg_buy_prop', 'flow_struct_buy_change', 'lg_elg_net_buy_vol_change', 'flow_lg_elg_accel', 'chip_concentration_range', 'chip_skewness', 'floating_chip_proxy', 'cost_support_15pct_change', 'cat_winner_price_zone', 'flow_chip_consistency', 'profit_taking_vs_absorb', 'cat_is_positive', 'upside_vol', 'downside_vol', 'vol_ratio', 'return_skew', 'return_kurtosis', 'volume_change_rate', 'cat_volume_breakout', 'turnover_deviation', 'cat_turnover_spike', 'avg_volume_ratio', 'cat_volume_ratio_breakout', 'vol_spike', 'vol_std_5', 'atr_14', 'atr_6', 'obv', 'maobv_6', 'rsi_3', 'return_5', 'return_20', 'std_return_5', 'std_return_90', 'std_return_90_2', 'act_factor1', 'act_factor2', 'act_factor3', 'act_factor4', 'rank_act_factor1', 'rank_act_factor2', 'rank_act_factor3', 'cov', 'delta_cov', 'alpha_22_improved', 'alpha_003', 'alpha_007', 'alpha_013', 'vol_break', 'weight_roc5', 'smallcap_concentration', 'cost_stability', 'high_cost_break_days', 'liquidity_risk', 'turnover_std', 'mv_volatility', 'volume_growth', 'mv_growth', 'momentum_factor', 'resonance_factor', 'log_close', 'cat_vol_spike', 'up', 'down', 'obv_maobv_6', 'std_return_5_over_std_return_90', 'std_return_90_minus_std_return_90_2', 'cat_af2', 'cat_af3', 'cat_af4', 'act_factor5', 'act_factor6', 'active_buy_volume_large', 'active_buy_volume_big', 'active_buy_volume_small', 'buy_lg_vol_minus_sell_lg_vol', 'buy_elg_vol_minus_sell_elg_vol', 'ctrl_strength', 'low_cost_dev', 'asymmetry', 'lock_factor', 'cat_vol_break', 'cost_atr_adj', 'cat_golden_resonance', 'mv_turnover_ratio', 'mv_adjusted_volume', 'mv_weighted_turnover', 'nonlinear_mv_volume', 'mv_volume_ratio', 'mv_momentum', 'lg_flow_mom_corr_20_60', 'lg_flow_accel', 'profit_pressure', 'underwater_resistance', 'cost_conc_std_20', 'profit_decay_20', 'vol_amp_loss_20', 'vol_drop_profit_cnt_5', 'lg_flow_vol_interact_20', 'cost_break_confirm_cnt_5', 'atr_norm_channel_pos_14', 'turnover_diff_skew_20', 'lg_sm_flow_diverge_20', 'pullback_strong_20_20', 'vol_wgt_hist_pos_20', 'vol_adj_roc_20', 'cs_rank_net_lg_flow_val', 'cs_rank_elg_buy_ratio', 'cs_rank_rel_profit_margin', 'cs_rank_cost_breadth', 'cs_rank_dist_to_upper_cost', 'cs_rank_winner_rate', 'cs_rank_intraday_range', 'cs_rank_close_pos_in_range', 'cs_rank_pos_in_hist_range', 'cs_rank_vol_x_profit_margin', 'cs_rank_lg_flow_price_concordance', 'cs_rank_turnover_per_winner', 'cs_rank_volume_ratio', 'cs_rank_elg_buy_sell_sm_ratio', 'cs_rank_cost_dist_vol_ratio', 'cs_rank_size', 'cat_up_limit', 'industry_obv', 'industry_return_5', 'industry_return_20', 'industry__ema_5', 'industry__ema_13', 'industry__ema_20', 'industry__ema_60', 'industry_act_factor1', 'industry_act_factor2', 'industry_act_factor3', 'industry_act_factor4', 'industry_act_factor5', 'industry_act_factor6', 'industry_rank_act_factor1', 'industry_rank_act_factor2', 'industry_rank_act_factor3', 'industry_return_5_percentile', 'industry_return_20_percentile', '000852.SH_MACD', '000905.SH_MACD', '399006.SZ_MACD', '000852.SH_MACD_hist', '000905.SH_MACD_hist', '399006.SZ_MACD_hist', '000852.SH_RSI', '000905.SH_RSI', '399006.SZ_RSI', '000852.SH_Signal_line', '000905.SH_Signal_line', '399006.SZ_Signal_line', '000852.SH_amount_change_rate', '000905.SH_amount_change_rate', '399006.SZ_amount_change_rate', '000852.SH_amount_mean', '000905.SH_amount_mean', '399006.SZ_amount_mean', '000852.SH_daily_return', '000905.SH_daily_return', '399006.SZ_daily_return', '000852.SH_up_ratio_20d', '000905.SH_up_ratio_20d', '399006.SZ_up_ratio_20d', '000852.SH_volatility', '000905.SH_volatility', '399006.SZ_volatility', '000852.SH_volume_change_rate', '000905.SH_volume_change_rate', '399006.SZ_volume_change_rate']\n",
"去除极值\n",
"开始截面 MAD 去极值处理 (k=3.0)...\n"
@@ -1409,7 +1303,7 @@
"name": "stderr",
"output_type": "stream",
"text": [
"MAD Filtering: 100%|██████████| 131/131 [00:13<00:00, 10.05it/s]\n"
"MAD Filtering: 100%|██████████| 131/131 [00:13<00:00, 9.90it/s]\n"
]
},
{
@@ -1424,7 +1318,7 @@
"name": "stderr",
"output_type": "stream",
"text": [
"MAD Filtering: 100%|██████████| 131/131 [00:16<00:00, 8.05it/s]\n"
"MAD Filtering: 100%|██████████| 131/131 [00:14<00:00, 8.90it/s]\n"
]
},
{
@@ -1464,13 +1358,13 @@
"截面 MAD 去极值处理完成。\n",
"feature_columns: ['vol', 'pct_chg', 'turnover_rate', 'volume_ratio', 'winner_rate', 'undist_profit_ps', 'ocfps', 'AR', 'BR', 'AR_BR', 'cashflow_to_ev_factor', 'book_to_price_ratio', 'turnover_rate_mean_5', 'variance_20', 'bbi_ratio_factor', 'daily_deviation', 'lg_elg_net_buy_vol', 'flow_lg_elg_intensity', 'sm_net_buy_vol', 'total_buy_vol', 'lg_elg_buy_prop', 'flow_struct_buy_change', 'lg_elg_net_buy_vol_change', 'flow_lg_elg_accel', 'chip_concentration_range', 'chip_skewness', 'floating_chip_proxy', 'cost_support_15pct_change', 'cat_winner_price_zone', 'flow_chip_consistency', 'profit_taking_vs_absorb', 'cat_is_positive', 'upside_vol', 'downside_vol', 'vol_ratio', 'return_skew', 'return_kurtosis', 'volume_change_rate', 'cat_volume_breakout', 'turnover_deviation', 'cat_turnover_spike', 'avg_volume_ratio', 'cat_volume_ratio_breakout', 'vol_spike', 'vol_std_5', 'atr_14', 'atr_6', 'obv', 'maobv_6', 'rsi_3', 'return_5', 'return_20', 'std_return_5', 'std_return_90', 'std_return_90_2', 'act_factor1', 'act_factor2', 'act_factor3', 'act_factor4', 'rank_act_factor1', 'rank_act_factor2', 'rank_act_factor3', 'cov', 'delta_cov', 'alpha_22_improved', 'alpha_003', 'alpha_007', 'alpha_013', 'vol_break', 'weight_roc5', 'smallcap_concentration', 'cost_stability', 'high_cost_break_days', 'liquidity_risk', 'turnover_std', 'mv_volatility', 'volume_growth', 'mv_growth', 'momentum_factor', 'resonance_factor', 'log_close', 'cat_vol_spike', 'up', 'down', 'obv_maobv_6', 'std_return_5_over_std_return_90', 'std_return_90_minus_std_return_90_2', 'cat_af2', 'cat_af3', 'cat_af4', 'act_factor5', 'act_factor6', 'active_buy_volume_large', 'active_buy_volume_big', 'active_buy_volume_small', 'buy_lg_vol_minus_sell_lg_vol', 'buy_elg_vol_minus_sell_elg_vol', 'ctrl_strength', 'low_cost_dev', 'asymmetry', 'lock_factor', 'cat_vol_break', 'cost_atr_adj', 'cat_golden_resonance', 'mv_turnover_ratio', 'mv_adjusted_volume', 'mv_weighted_turnover', 'nonlinear_mv_volume', 'mv_volume_ratio', 'mv_momentum', 'lg_flow_mom_corr_20_60', 'lg_flow_accel', 'profit_pressure', 'underwater_resistance', 'cost_conc_std_20', 'profit_decay_20', 'vol_amp_loss_20', 'vol_drop_profit_cnt_5', 'lg_flow_vol_interact_20', 'cost_break_confirm_cnt_5', 'atr_norm_channel_pos_14', 'turnover_diff_skew_20', 'lg_sm_flow_diverge_20', 'pullback_strong_20_20', 'vol_wgt_hist_pos_20', 'vol_adj_roc_20', 'cs_rank_net_lg_flow_val', 'cs_rank_elg_buy_ratio', 'cs_rank_rel_profit_margin', 'cs_rank_cost_breadth', 'cs_rank_dist_to_upper_cost', 'cs_rank_winner_rate', 'cs_rank_intraday_range', 'cs_rank_close_pos_in_range', 'cs_rank_pos_in_hist_range', 'cs_rank_vol_x_profit_margin', 'cs_rank_lg_flow_price_concordance', 'cs_rank_turnover_per_winner', 'cs_rank_volume_ratio', 'cs_rank_elg_buy_sell_sm_ratio', 'cs_rank_cost_dist_vol_ratio', 'cs_rank_size', 'cat_up_limit', 'industry_obv', 'industry_return_5', 'industry_return_20', 'industry__ema_5', 'industry__ema_13', 'industry__ema_20', 'industry__ema_60', 'industry_act_factor1', 'industry_act_factor2', 'industry_act_factor3', 'industry_act_factor4', 'industry_act_factor5', 'industry_act_factor6', 'industry_rank_act_factor1', 'industry_rank_act_factor2', 'industry_rank_act_factor3', 'industry_return_5_percentile', 'industry_return_20_percentile', '000852.SH_MACD', '000905.SH_MACD', '399006.SZ_MACD', '000852.SH_MACD_hist', '000905.SH_MACD_hist', '399006.SZ_MACD_hist', '000852.SH_RSI', '000905.SH_RSI', '399006.SZ_RSI', '000852.SH_Signal_line', '000905.SH_Signal_line', '399006.SZ_Signal_line', '000852.SH_amount_change_rate', '000905.SH_amount_change_rate', '399006.SZ_amount_change_rate', '000852.SH_amount_mean', '000905.SH_amount_mean', '399006.SZ_amount_mean', '000852.SH_daily_return', '000905.SH_daily_return', '399006.SZ_daily_return', '000852.SH_up_ratio_20d', '000905.SH_up_ratio_20d', '399006.SZ_up_ratio_20d', '000852.SH_volatility', '000905.SH_volatility', '399006.SZ_volatility', '000852.SH_volume_change_rate', '000905.SH_volume_change_rate', '399006.SZ_volume_change_rate']\n",
"df最小日期: 2019-01-02\n",
"df最大日期: 2026-02-06\n",
"2055944\n",
"df最大日期: 2026-02-13\n",
"2055886\n",
"train_data最小日期: 2020-01-02\n",
"train_data最大日期: 2022-12-30\n",
"2297633\n",
"2312688\n",
"test_data最小日期: 2023-01-03\n",
"test_data最大日期: 2026-02-06\n",
"test_data最大日期: 2026-02-13\n",
" ts_code trade_date log_circ_mv\n",
"0 000001.SZ 2019-01-02 16.574219\n",
"1 000001.SZ 2019-01-03 16.583965\n",
@@ -1483,7 +1377,7 @@
"train_data = df[filter_index & (df['trade_date'] <= split_date) & (df['trade_date'] >= '2020-01-01')]\n",
"test_data = df[(df['trade_date'] >= split_date)]\n",
"\n",
"print(df[['ts_code', 'trade_date', 'log_circ_mv']].head(3))\n",
"print(df[['ts_code', 'trade_date', 'log_circ_mv']].tail(3))\n",
"\n",
"industry_df = industry_df.sort_values(by=['trade_date'])\n",
"index_data = index_data.sort_values(by=['trade_date'])\n",
@@ -1606,7 +1500,7 @@
},
{
"cell_type": "code",
"execution_count": 18,
"execution_count": null,
"id": "3ff2d1c5",
"metadata": {},
"outputs": [],
@@ -1747,14 +1641,14 @@
},
{
"cell_type": "code",
"execution_count": 19,
"execution_count": null,
"id": "a5bbb8be",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<catboost.core.CatBoostClassifier at 0x7b3eec333d70>"
"<catboost.core.CatBoostClassifier at 0x752dd29c0e30>"
]
},
"execution_count": 19,
@@ -1772,7 +1666,7 @@
},
{
"cell_type": "code",
"execution_count": 20,
"execution_count": null,
"id": "5d1522a7538db91b",
"metadata": {
"ExecuteTime": {
@@ -1811,7 +1705,7 @@
},
{
"cell_type": "code",
"execution_count": 21,
"execution_count": null,
"id": "09b1799e",
"metadata": {},
"outputs": [
@@ -1833,7 +1727,7 @@
},
{
"cell_type": "code",
"execution_count": 22,
"execution_count": null,
"id": "e53b209a",
"metadata": {},
"outputs": [
@@ -1841,7 +1735,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"5584 2055944\n",
"5584 2055886\n",
" ts_code trade_date turnover_rate\n",
"0 000001.SZ 2023-01-03 1.1307\n",
"1 000001.SZ 2023-01-04 1.1284\n",
@@ -1849,13 +1743,13 @@
"3 000001.SZ 2023-01-06 0.6162\n",
"4 000001.SZ 2023-01-09 0.5450\n",
"... ... ... ...\n",
"2297628 605599.SH 2026-02-02 2.6968\n",
"2297629 605599.SH 2026-02-03 1.6084\n",
"2297630 605599.SH 2026-02-04 3.9328\n",
"2297631 605599.SH 2026-02-05 3.0072\n",
"2297632 605599.SH 2026-02-06 3.1129\n",
"2312683 605599.SH 2026-02-09 2.6607\n",
"2312684 605599.SH 2026-02-10 2.5722\n",
"2312685 605599.SH 2026-02-11 2.1806\n",
"2312686 605599.SH 2026-02-12 1.4513\n",
"2312687 605599.SH 2026-02-13 1.5153\n",
"\n",
"[2297633 rows x 3 columns]\n"
"[2312688 rows x 3 columns]\n"
]
}
],
@@ -1881,7 +1775,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.11"
"version": "3.13.2"
}
},
"nbformat": 4,

View File

@@ -1503,3 +1503,13 @@ trade_date,score,ts_code
2026-02-05,0.6383257473564533,002193.SZ
2026-02-06,0.45969830258066396,600493.SH
2026-02-06,0.6311025962732058,002193.SZ
2026-02-09,0.4478161764829177,002719.SZ
2026-02-09,0.6157362204288197,603729.SH
2026-02-10,0.3999390029537349,002719.SZ
2026-02-10,0.5896469073813839,002193.SZ
2026-02-11,0.49232775247140015,002193.SZ
2026-02-11,0.628548611096168,603729.SH
2026-02-12,0.4321547861568006,002193.SZ
2026-02-12,0.5119718467949886,603729.SH
2026-02-13,0.39079335569325513,603729.SH
2026-02-13,0.46226975723447805,002193.SZ
1 trade_date,score,ts_code
1503 2026-02-05,0.6383257473564533,002193.SZ
1504 2026-02-06,0.45969830258066396,600493.SH
1505 2026-02-06,0.6311025962732058,002193.SZ
1506 2026-02-09,0.4478161764829177,002719.SZ
1507 2026-02-09,0.6157362204288197,603729.SH
1508 2026-02-10,0.3999390029537349,002719.SZ
1509 2026-02-10,0.5896469073813839,002193.SZ
1510 2026-02-11,0.49232775247140015,002193.SZ
1511 2026-02-11,0.628548611096168,603729.SH
1512 2026-02-12,0.4321547861568006,002193.SZ
1513 2026-02-12,0.5119718467949886,603729.SH
1514 2026-02-13,0.39079335569325513,603729.SH
1515 2026-02-13,0.46226975723447805,002193.SZ

View File

@@ -58,7 +58,13 @@ QMT 模块是 NewStock 量化交易系统的实盘交易执行模块,通过 `x
交易信号通过 Redis 消息队列传递,每个策略对应一个独立的队列。消息格式为 JSON 对象,包含股票代码、操作类型、价格、时间戳等字段。系统对每条消息进行严格校验,包括日期校验、时间戳校验、必填字段校验等,确保只有当天的有效指令才会被执行。
买入逻辑支持槽位控制,通过 `total_slots` 参数限制同时持有的股票数量。系统根据可用资金和目标槽位自动计算每只股票的买入数量,金额过小或股数不足的请求会被拦截。卖出逻辑则根据 Redis 中的虚拟持仓和实盘可用持仓计算实际卖出数量,确保不会超卖。
买入逻辑支持两种模式:
1. **槽位控制模式**:通过 `total_slots` 参数限制同时持有的股票数量。系统根据可用资金和目标槽位自动计算每只股票的买入数量,金额过小或股数不足的请求会被拦截。
2. **仓位百分比模式**:通过 `position_pct` 参数指定目标持仓占账户总资产的比例。系统根据账户总资产计算目标金额,然后转换为具体股数进行下单。该模式无持仓数量限制。
卖出逻辑根据策略配置模式有所不同:槽位模式下根据 Redis 中的虚拟持仓和实盘可用持仓计算实际卖出数量;百分比模式下执行清仓操作。
### 3.3 持仓管理
@@ -193,9 +199,41 @@ QMT 模块是 NewStock 量化交易系统的实盘交易执行模块,通过 `x
| `redis` | Object | Redis 连接配置,支持 host、port、db、password 等参数 |
| `qmt_terminals` | Array | QMT 终端列表,每个终端包含唯一标识、别名、路径、账户信息 |
| `strategies` | Object | 策略配置,键为策略名,值包含使用的终端 ID 和执行参数 |
| `total_slots` | Integer | 策略的最大持仓股票数量 |
| `total_slots` | Integer | 策略的最大持仓股票数量(槽位模式) |
| `order_mode` | String | 下单模式,可选 `slots`(槽位)或 `percentage`(百分比),默认为 `slots` |
| `auto_reconnect` | Object | 自动重连配置,包含启用状态和执行时间 |
**槽位模式配置示例:**
```json
{
"strategies": {
"strategy_a": {
"qmt_id": "terminal_001",
"order_mode": "slots",
"total_slots": 5,
"execution": {
"buy_amount_per_stock": 20000,
"min_buy_amount": 2000
}
}
}
}
```
**百分比模式配置示例:**
```json
{
"strategies": {
"strategy_b": {
"qmt_id": "terminal_001",
"order_mode": "percentage"
}
}
}
```
## 6. Web 仪表盘功能
### 6.1 功能概览
@@ -317,7 +355,152 @@ Web 仪表盘基于 Vue 3 和 Naive UI 组件库开发,提供可视化的系
| 聚宽 | `.XSHE` / `.XSHG` | `000001.XSHE``600519.XSHG` |
| QMT | `.SZ` / `.SH` | `000001.SZ``600519.SH` |
## 8. 系统架构
## 8. 百分比下单信号发送端qmt_percentage_sender.py
### 8.1 模块定位
`qmt_percentage_sender.py` 是基于**仓位百分比**的 QMT 信号发送端,与槽位模式的 `qmt_signal_sender.py` 并行存在。该模块用于配置为 `order_mode: "percentage"` 的策略,通过指定目标持仓占账户总资产的比例来触发交易。
### 8.2 核心函数
#### `send_qmt_percentage_signal(code, position_pct, action, price, is_backtest, timestamp, redis_config)`
| 参数 | 类型 | 说明 |
|------|------|------|
| `code` | str | 股票代码,聚宽格式(如 `000001.XSHE``600519.XSHG` |
| `position_pct` | float | 目标持仓占总资产的比例,范围 0.0 ~ 1.0(如 0.2 表示 20% |
| `action` | str | 交易动作,固定为 `"BUY"``"SELL"` |
| `price` | float | 当前最新价格,用于实盘限价单参考 |
| `is_backtest` | bool | 是否为回测模式True/False |
| `timestamp` | str | 时间戳字符串,格式 `"YYYY-MM-DD HH:MM:SS"` |
| `redis_config` | dict | Redis 连接配置,包含 `host``port``password``db``strategy_name` 等字段 |
### 8.3 处理流程
```
策略触发信号
1. 环境判断与流量控制
├─ 实盘模式 → 直接通过
└─ 回测模式 → 限制最多发送 10 条(防止回测刷爆队列)
2. 建立 Redis 连接socket_timeout=1s
3. 数据转换与规范化
└─ 股票代码格式转换:.XSHE → .SZ.XSHG → .SH
4. 构建 JSON 消息体(包含 position_pct 字段)
5. 队列路由
├─ 回测 → {strategy_name}_backtestTTL: 1 小时)
└─ 实盘 → {strategy_name}_realTTL: 7 天)
6. 控制台日志输出
```
### 8.4 消息格式
发送到 Redis 队列的 JSON 消息结构:
```json
{
"strategy_name": "my_strategy",
"stock_code": "000001.SZ",
"action": "BUY",
"price": 15.50,
"position_pct": 0.2,
"timestamp": "2026-02-17 14:30:00",
"is_backtest": false
}
```
| 字段 | 类型 | 说明 |
|------|------|------|
| `strategy_name` | str | 策略名称,来自 `redis_config['strategy_name']`,用于队列路由和持仓管理 |
| `stock_code` | str | QMT 格式的股票代码(`.SZ` / `.SH` |
| `action` | str | 交易动作,`BUY``SELL` |
| `price` | float | 信号触发时的最新价格 |
| `position_pct` | float | 目标持仓占账户总资产的比例,范围 0.0 ~ 1.0 |
| `timestamp` | str | 信号生成时间,格式 `YYYY-MM-DD HH:MM:SS` |
| `is_backtest` | bool | 是否为回测环境发出的信号 |
### 8.5 买卖意图判定逻辑
与槽位模式不同,百分比模式需要**显式指定**交易动作:
- **`action = "BUY"`**:策略意向买入该股票,目标持仓占比为 `position_pct`。交易引擎根据账户总资产计算目标金额,然后转换为具体股数下单。
- **`action = "SELL"`**:策略意向清仓该股票。百分比模式下卖出采用简化逻辑,直接执行清仓操作。
### 8.6 买入计算公式
当 QMT 端接收到百分比模式的买入信号时,按以下公式计算买入股数:
```
目标金额 = 账户总资产 × position_pct
可用金额 = min(目标金额, 可用资金)
买入股数 = int(可用金额 / 价格 / 100) × 100
```
**边界处理:**
- 单笔金额 < 2000 元 → 拦截不下单
- 计算股数 < 100 股 → 拦截不下单
- 价格 ≤ 0 → 强制设为 1.0(仅测试用)
### 8.7 与槽位模式的对比
| 特性 | 槽位模式 (slots) | 百分比模式 (percentage) |
|------|------------------|------------------------|
| 核心参数 | `total_slots` | `position_pct` |
| 持仓限制 | 有(同时持仓数量限制) | 无 |
| 资金分配 | 按剩余槽位均分资金 | 按总资产比例计算 |
| 卖出逻辑 | 按持仓数量计算 | 清仓 |
| 配置方式 | 配置文件设置 `order_mode: "slots"` | 配置文件设置 `order_mode: "percentage"` |
| 信号发送 | `send_qmt_signal()` | `send_qmt_percentage_signal()` |
### 8.8 使用示例
```python
from qmt_percentage_sender import send_qmt_percentage_signal
# Redis 配置
redis_config = {
"host": "localhost",
"port": 6379,
"password": None,
"db": 0,
"strategy_name": "MyPercentageStrategy"
}
# 买入信号:目标持仓占账户总资产的 20%
send_qmt_percentage_signal(
code="000001.XSHE",
position_pct=0.2,
action="BUY",
price=15.5,
is_backtest=False,
timestamp="2026-02-17 14:30:00",
redis_config=redis_config
)
# 卖出信号:清仓
send_qmt_percentage_signal(
code="000001.XSHE",
position_pct=0,
action="SELL",
price=15.8,
is_backtest=False,
timestamp="2026-02-17 14:35:00",
redis_config=redis_config
)
```
## 9. 系统架构
### 8.1 组件关系图
@@ -400,7 +583,7 @@ Web 仪表盘基于 Vue 3 和 Naive UI 组件库开发,提供可视化的系
7. **订单执行**:调用 QMT API 下单,成功则缓存订单信息
8. **状态更新**:标记虚拟持仓,异步等待成交回调
## 9. 启动与停止
## 10. 启动与停止
### 9.1 Windows 启动
@@ -427,7 +610,7 @@ python run.py
|------|----------|------|
| API 服务 | 8001 | Web 仪表盘和 RESTful API 监听端口 |
## 10. 注意事项
## 11. 注意事项
1. **QMT 终端要求**:确保 QMT 终端已登录且路径配置正确
2. **Redis 服务**:系统依赖 Redis 运行,请确保 Redis 服务可用

View File

@@ -0,0 +1,102 @@
import redis
import json
# --- 模块级全局变量 ---
_BACKTEST_SEND_COUNT = 0
def send_qmt_percentage_signal(
code, position_pct, action, price, is_backtest, timestamp, redis_config
):
"""
发送基于仓位百分比的信号到 Redis
参数:
- code: 股票代码 (聚宽格式: 000001.XSHE)
- position_pct: 目标持仓占总资产的比例 (0.0 ~ 1.0,如 0.2 表示 20%)
- action: 交易动作,"BUY""SELL"
- price: 当前最新价格 (用于实盘限价单参考)
- is_backtest: 是否为回测模式 (True/False)
- timestamp: 时间戳字符串,格式 "YYYY-MM-DD HH:MM:SS"
- redis_config: Redis配置字典包含 host, port, password, db, strategy_name
"""
global _BACKTEST_SEND_COUNT
try:
# ---------------------------------------------------------
# 1. 环境判断与流量控制
# ---------------------------------------------------------
if is_backtest:
if _BACKTEST_SEND_COUNT >= 10:
return
_BACKTEST_SEND_COUNT += 1
# ---------------------------------------------------------
# 2. 建立 Redis 连接
# ---------------------------------------------------------
r = redis.Redis(
host=redis_config["host"],
port=redis_config["port"],
password=redis_config.get("password"),
db=redis_config.get("db", 0),
decode_responses=True,
socket_timeout=1,
)
# ---------------------------------------------------------
# 3. 数据转换与规范化
# ---------------------------------------------------------
# 股票代码格式转换: 聚宽(.XSHE/.XSHG) -> QMT(.SZ/.SH)
qmt_code = code
if code.endswith(".XSHE"):
qmt_code = code.replace(".XSHE", ".SZ")
elif code.endswith(".XSHG"):
qmt_code = code.replace(".XSHG", ".SH")
# 校验 action 参数
if action not in ["BUY", "SELL"]:
print(f"[Error] 无效的 action 参数: {action},必须是 'BUY''SELL'")
return
# ---------------------------------------------------------
# 4. 构建消息体
# ---------------------------------------------------------
base_strategy_name = redis_config.get("strategy_name", "default_strategy")
msg = {
"strategy_name": base_strategy_name,
"stock_code": qmt_code,
"action": action,
"price": price,
"position_pct": float(position_pct),
"timestamp": timestamp,
"is_backtest": is_backtest,
}
json_payload = json.dumps(msg)
# ---------------------------------------------------------
# 5. 队列路由
# ---------------------------------------------------------
queue_key = (
f"{base_strategy_name}_backtest"
if is_backtest
else f"{base_strategy_name}_real"
)
expire_seconds = 3600 if is_backtest else 604800
r.rpush(queue_key, json_payload)
r.expire(queue_key, expire_seconds)
# ---------------------------------------------------------
# 6. 控制台输出
# ---------------------------------------------------------
log_prefix = "【回测】" if is_backtest else "【实盘】"
pct_display = f"{position_pct * 100:.1f}%"
desc = f"目标仓位:{pct_display}" if action == "BUY" else "清仓"
print(
f"{log_prefix} 百分比信号 -> {qmt_code} | 动作:{action} | {desc} | 价格:{price} | 时间:{timestamp}"
)
except Exception as e:
print(f"[Error] 发送QMT百分比信号失败: {e}")

View File

@@ -285,7 +285,251 @@ class MyXtQuantTraderCallback(XtQuantTraderCallback):
# ================= 5. 核心消息处理 (重写版:拒绝静默失败) =================
def process_strategy_queue(strategy_name, r_client, xt_trader, acc, pos_manager):
def get_strategy_config(strategy_name, config):
"""获取策略配置,支持新旧配置格式兼容"""
strategies = config.get("strategies", {})
# 如果 strategies 是列表(旧格式),转换为默认配置
if isinstance(strategies, list):
return {"order_mode": "slots", "total_slots": 5}
# 获取策略配置
strategy_config = strategies.get(strategy_name, {})
# 设置默认值
result = {
"order_mode": strategy_config.get("order_mode", "slots"),
"total_slots": strategy_config.get("total_slots", 5),
}
return result
def process_percentage_buy(
strategy_name, stock_code, price, position_pct, xt_trader, acc
):
"""处理百分比模式的买入逻辑"""
logger.info(f"[百分比模式] 处理买入: {stock_code}, 目标占比: {position_pct}")
# 查询资产
asset = xt_trader.query_stock_asset(acc)
if not asset:
logger.error("API 错误: query_stock_asset 返回 None可能是 QMT 断连或未同步")
return
total_asset = asset.total_asset
available_cash = asset.cash
logger.info(
f"[百分比模式] 账户总资产: {total_asset:.2f}, 可用资金: {available_cash:.2f}"
)
# 计算目标金额
target_amount = total_asset * position_pct
actual_amount = min(target_amount, available_cash)
logger.info(
f"[百分比模式] 目标金额: {target_amount:.2f}, 实际可用: {actual_amount:.2f}"
)
# 检查最小金额限制
if actual_amount < 2000:
logger.warning(f"[百分比模式] 拦截买入: 金额过小 ({actual_amount:.2f} < 2000)")
return
# 价格校验
if price <= 0:
logger.warning(
f"[百分比模式] 价格异常: {price}强制设为1.0以计算股数(仅测试用)"
)
price = 1.0
# 计算股数
vol = int(actual_amount / price / 100) * 100
logger.info(
f"[百分比模式] 计算股数: 资金{actual_amount:.2f} / 价格{price} -> {vol}"
)
if vol < 100:
logger.warning(f"[百分比模式] 拦截买入: 股数不足 100 ({vol})")
return
# 执行下单
oid = xt_trader.order_stock(
acc,
stock_code,
xtconstant.STOCK_BUY,
vol,
xtconstant.FIX_PRICE,
price,
strategy_name,
"PyBuyPct",
)
if oid != -1:
logger.info(f"[百分比模式] √√√ 下单成功: ID={oid} {stock_code} 买入 {vol}")
ORDER_CACHE[oid] = (strategy_name, stock_code, "BUY")
else:
logger.error(
f"[百分比模式] XXX 下单请求被拒绝 (Result=-1),请检查 QMT 终端报错"
)
def process_percentage_sell(strategy_name, stock_code, price, xt_trader, acc):
"""处理百分比模式的卖出逻辑(清仓)"""
logger.info(f"[百分比模式] 处理卖出: {stock_code} (清仓)")
# 查询实盘持仓
real_pos = xt_trader.query_stock_positions(acc)
if real_pos is None:
logger.error("[百分比模式] API 错误: query_stock_positions 返回 None")
return
rp = next((p for p in real_pos if p.stock_code == stock_code), None)
can_use = rp.can_use_volume if rp else 0
logger.info(f"[百分比模式] 股票 {stock_code} 实盘可用持仓: {can_use}")
if can_use <= 0:
logger.warning(f"[百分比模式] 拦截卖出: 无可用持仓")
return
# 执行清仓
logger.info(f"[百分比模式] 执行清仓: {stock_code} @ {price}, 数量: {can_use}")
oid = xt_trader.order_stock(
acc,
stock_code,
xtconstant.STOCK_SELL,
can_use,
xtconstant.FIX_PRICE,
price,
strategy_name,
"PySellPct",
)
if oid != -1:
logger.info(f"[百分比模式] √√√ 下单成功: ID={oid} {stock_code} 卖出 {can_use}")
ORDER_CACHE[oid] = (strategy_name, stock_code, "SELL")
else:
logger.error(f"[百分比模式] XXX 下单请求被拒绝 (Result=-1)")
def process_slots_buy(
strategy_name, stock_code, price, total_slots, xt_trader, acc, pos_manager
):
"""处理槽位模式的买入逻辑(原有逻辑保持不变)"""
holding = pos_manager.get_holding_count(strategy_name)
empty = total_slots - holding
logger.info(
f"[槽位模式] 检查持仓: 当前占用 {holding} / 总槽位 {total_slots} -> 剩余 {empty}"
)
if empty <= 0:
logger.warning(f"[槽位模式] 拦截买入: 槽位已满,不执行下单")
return
# 查询资金
asset = xt_trader.query_stock_asset(acc)
if not asset:
logger.error(
"[槽位模式] API 错误: query_stock_asset 返回 None可能是 QMT 断连或未同步"
)
return
logger.info(f"[槽位模式] 当前可用资金: {asset.cash:.2f}")
amt = asset.cash / empty
if amt < 2000:
logger.warning(f"[槽位模式] 拦截买入: 单笔金额过小 ({amt:.2f} < 2000)")
return
if price <= 0:
logger.warning(f"[槽位模式] 价格异常: {price}强制设为1.0以计算股数(仅测试用)")
price = 1.0
vol = int(amt / price / 100) * 100
logger.info(f"[槽位模式] 计算股数: 资金{amt:.2f} / 价格{price} -> {vol}")
if vol < 100:
logger.warning(f"[槽位模式] 拦截买入: 股数不足 100 ({vol})")
return
# 执行下单
oid = xt_trader.order_stock(
acc,
stock_code,
xtconstant.STOCK_BUY,
vol,
xtconstant.FIX_PRICE,
price,
strategy_name,
"PyBuy",
)
if oid != -1:
logger.info(f"[槽位模式] √√√ 下单成功: ID={oid} {stock_code} 买入 {vol}")
ORDER_CACHE[oid] = (strategy_name, stock_code, "BUY")
pos_manager.mark_holding(strategy_name, stock_code)
else:
logger.error(f"[槽位模式] XXX 下单请求被拒绝 (Result=-1),请检查 QMT 终端报错")
def process_slots_sell(strategy_name, stock_code, price, xt_trader, acc, pos_manager):
"""处理槽位模式的卖出逻辑(原有逻辑保持不变)"""
v_vol = pos_manager.get_position(strategy_name, stock_code)
logger.info(f"[槽位模式] 卖出 - Redis 记录虚拟持仓: {v_vol}")
if v_vol > 0:
logger.info(f"[槽位模式] 卖出 - 正在查询实盘持仓: {stock_code}")
real_pos = xt_trader.query_stock_positions(acc)
logger.info(
f"[槽位模式] 卖出 - 实盘持仓查询完成,获取到 {len(real_pos) if real_pos else 0} 条记录"
)
if real_pos is None:
logger.error("[槽位模式] API 错误: query_stock_positions 返回 None")
return
rp = next((p for p in real_pos if p.stock_code == stock_code), None)
can_use = rp.can_use_volume if rp else 0
logger.info(f"[槽位模式] 卖出 - 股票 {stock_code} 实盘可用持仓: {can_use}")
final = min(v_vol, can_use)
logger.info(f"[槽位模式] 卖出 - 计算卖出量: min({v_vol}, {can_use}) = {final}")
if final > 0:
logger.info(
f"[槽位模式] 卖出 - 执行卖出订单: {stock_code} @ {price}, 数量: {final}"
)
oid = xt_trader.order_stock(
acc,
stock_code,
xtconstant.STOCK_SELL,
final,
xtconstant.FIX_PRICE,
price,
strategy_name,
"PySell",
)
if oid != -1:
logger.info(
f"[槽位模式] √√√ 下单成功: ID={oid} {stock_code} 卖出 {final}"
)
ORDER_CACHE[oid] = (strategy_name, stock_code, "SELL")
else:
logger.error(f"[槽位模式] XXX 下单请求被拒绝 (Result=-1)")
else:
logger.warning(
f"[槽位模式] 拦截卖出: 最终计算卖出量为 0 (虚拟:{v_vol}, 实盘:{can_use})"
)
else:
logger.warning(f"[槽位模式] 拦截卖出: Redis 中无此持仓记录,忽略")
def process_strategy_queue(
strategy_name, r_client, xt_trader, acc, pos_manager, config
):
queue_key = f"{strategy_name}_real"
# 1. 获取消息
@@ -326,130 +570,62 @@ def process_strategy_queue(strategy_name, r_client, xt_trader, acc, pos_manager)
stock_code = data.get("stock_code")
action = data.get("action")
price = float(data.get("price", 0))
total_slots = int(data.get("total_slots", 1))
if not stock_code or not action:
logger.error(f"缺少关键字段: Code={stock_code}, Action={action}")
return
# 5. 获取策略配置,确定下单模式
strategy_config = get_strategy_config(strategy_name, config)
order_mode = strategy_config.get("order_mode", "slots")
logger.info(
f"解析成功: {action} {stock_code} @ {price}, 目标槽位: {total_slots}"
f"解析成功: {action} {stock_code} @ {price}, 下单模式: {order_mode}"
)
# 5. QMT 存活检查
# 6. QMT 存活检查
if xt_trader is None or acc is None:
logger.error("严重错误: QMT 对象未初始化 (xt_trader is None)")
return
# 6. 买入逻辑
if action == "BUY":
holding = pos_manager.get_holding_count(strategy_name)
empty = total_slots - holding
# 7. 根据下单模式执行相应逻辑
if order_mode == "percentage":
# 百分比模式
position_pct = float(data.get("position_pct", 0))
logger.info(
f"检查持仓: 当前占用 {holding} / 总槽位 {total_slots} -> 剩余 {empty}"
)
if empty <= 0:
logger.warning(f"拦截买入: 槽位已满,不执行下单")
return
# 查询资金
asset = xt_trader.query_stock_asset(acc)
if not asset:
logger.error(
"API 错误: query_stock_asset 返回 None可能是 QMT 断连或未同步"
if action == "BUY":
process_percentage_buy(
strategy_name, stock_code, price, position_pct, xt_trader, acc
)
return
logger.info(f"当前可用资金: {asset.cash:.2f}")
amt = asset.cash / empty
if amt < 2000:
logger.warning(f"拦截买入: 单笔金额过小 ({amt:.2f} < 2000)")
return
if price <= 0:
logger.warning(f"价格异常: {price}强制设为1.0以计算股数(仅测试用)")
price = 1.0
vol = int(amt / price / 100) * 100
logger.info(f"计算股数: 资金{amt:.2f} / 价格{price} -> {vol}")
if vol < 100:
logger.warning(f"拦截买入: 股数不足 100 ({vol})")
return
# 执行下单
oid = xt_trader.order_stock(
acc,
stock_code,
xtconstant.STOCK_BUY,
vol,
xtconstant.FIX_PRICE,
price,
strategy_name,
"PyBuy",
)
if oid != -1:
logger.info(f"√√√ 下单成功: ID={oid} {stock_code} 买入 {vol}")
ORDER_CACHE[oid] = (strategy_name, stock_code, "BUY")
pos_manager.mark_holding(strategy_name, stock_code)
else:
logger.error(f"XXX 下单请求被拒绝 (Result=-1),请检查 QMT 终端报错")
# 7. 卖出逻辑
elif action == "SELL":
v_vol = pos_manager.get_position(strategy_name, stock_code)
logger.info(f"卖出 - Redis 记录虚拟持仓: {v_vol}")
if v_vol > 0:
logger.info(f"卖出 - 正在查询实盘持仓: {stock_code}")
real_pos = xt_trader.query_stock_positions(acc)
logger.info(
f"卖出 - 实盘持仓查询完成,获取到 {len(real_pos) if real_pos else 0} 条记录"
elif action == "SELL":
process_percentage_sell(
strategy_name, stock_code, price, xt_trader, acc
)
if real_pos is None:
logger.error("API 错误: query_stock_positions 返回 None")
return
rp = next((p for p in real_pos if p.stock_code == stock_code), None)
can_use = rp.can_use_volume if rp else 0
logger.info(f"卖出 - 股票 {stock_code} 实盘可用持仓: {can_use}")
final = min(v_vol, can_use)
logger.info(f"卖出 - 计算卖出量: min({v_vol}, {can_use}) = {final}")
if final > 0:
logger.info(
f"卖出 - 执行卖出订单: {stock_code} @ {price}, 数量: {final}"
)
oid = xt_trader.order_stock(
acc,
stock_code,
xtconstant.STOCK_SELL,
final,
xtconstant.FIX_PRICE,
price,
strategy_name,
"PySell",
)
if oid != -1:
logger.info(f"√√√ 下单成功: ID={oid} {stock_code} 卖出 {final}")
ORDER_CACHE[oid] = (strategy_name, stock_code, "SELL")
else:
logger.error(f"XXX 下单请求被拒绝 (Result=-1)")
else:
logger.warning(
f"拦截卖出: 最终计算卖出量为 0 (虚拟:{v_vol}, 实盘:{can_use})"
)
else:
logger.warning(f"拦截卖出: Redis 中无此持仓记录,忽略")
logger.error(f"未知的 Action: {action}")
else:
logger.error(f"未知的 Action: {action}")
# 槽位模式(默认)
total_slots = int(
data.get("total_slots", strategy_config.get("total_slots", 5))
)
if action == "BUY":
process_slots_buy(
strategy_name,
stock_code,
price,
total_slots,
xt_trader,
acc,
pos_manager,
)
elif action == "SELL":
process_slots_sell(
strategy_name, stock_code, price, xt_trader, acc, pos_manager
)
else:
logger.error(f"未知的 Action: {action}")
except Exception as e:
logger.error(f"消息处理发生未捕获异常: {str(e)}", exc_info=True)
@@ -662,7 +838,12 @@ def trading_loop():
settler.reset_flag()
for s in watch_list:
process_strategy_queue(
s, r, GLOBAL_STATE.xt_trader, GLOBAL_STATE.acc, pos_manager
s,
r,
GLOBAL_STATE.xt_trader,
GLOBAL_STATE.acc,
pos_manager,
CONFIG,
)
elif "150500" <= current_time_str <= "151000":