feat: 添加 Redis 消息展示功能到监控面板

- 新增 /api/messages API 接口,支持从 Redis Stream 读取消息
- 支持按策略筛选消息和分页展示
- 前端新增消息列表卡片,展示时间、策略、股票代码、动作、价格和状态
- 自动判断消息处理状态(已处理/待处理)
- 消息列表每30秒自动刷新,支持手动刷新
This commit is contained in:
2026-03-01 22:06:42 +08:00
parent e88ba5bcf9
commit 7bb0a0537b
14 changed files with 1814 additions and 806 deletions

View File

@@ -18,10 +18,10 @@
"Please upgrade to Gymnasium, the maintained drop-in replacement of Gym, or contact the authors of your software and request that they upgrade.\n",
"Users of this version of Gym should be able to simply replace 'import gym' with 'import gymnasium as gym' in the vast majority of cases.\n",
"See the migration guide at https://gymnasium.farama.org/introduction/migration_guide/ for additional information.\n",
"[206406:MainThread](2025-12-05 23:38:39,028) INFO - qlib.Initialization - [config.py:452] - default_conf: client.\n",
"[206406:MainThread](2025-12-05 23:38:39,028) WARNING - qlib.Initialization - [config.py:459] - Unrecognized config freq\n",
"[206406:MainThread](2025-12-05 23:38:39,034) INFO - qlib.Initialization - [__init__.py:75] - qlib successfully initialized based on client settings.\n",
"[206406:MainThread](2025-12-05 23:38:39,035) INFO - qlib.Initialization - [__init__.py:77] - data_path={'__DEFAULT_FREQ': PosixPath('/mnt/d/PyProject/NewStock/data/qlib')}\n"
"[177513:MainThread](2026-02-25 22:33:43,460) INFO - qlib.Initialization - [config.py:452] - default_conf: client.\n",
"[177513:MainThread](2026-02-25 22:33:43,461) WARNING - qlib.Initialization - [config.py:459] - Unrecognized config freq\n",
"[177513:MainThread](2026-02-25 22:33:43,467) INFO - qlib.Initialization - [__init__.py:75] - qlib successfully initialized based on client settings.\n",
"[177513:MainThread](2026-02-25 22:33:43,469) INFO - qlib.Initialization - [__init__.py:77] - data_path={'__DEFAULT_FREQ': PosixPath('/mnt/d/PyProject/NewStock/data/qlib')}\n"
]
},
{
@@ -96,7 +96,7 @@
"cyq perf\n",
"left merge on ['ts_code', 'trade_date']\n",
"<class 'pandas.core.frame.DataFrame'>\n",
"RangeIndex: 9367000 entries, 0 to 9366999\n",
"RangeIndex: 9436343 entries, 0 to 9436342\n",
"Data columns (total 33 columns):\n",
" # Column Dtype \n",
"--- ------ ----- \n",
@@ -134,7 +134,7 @@
" 31 weight_avg float64 \n",
" 32 winner_rate float64 \n",
"dtypes: bool(1), datetime64[ns](1), float64(30), object(1)\n",
"memory usage: 2.2+ GB\n",
"memory usage: 2.3+ GB\n",
"None\n"
]
}
@@ -172,6 +172,38 @@
"print(df.info())"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "5f3847ec",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" trade_date return_5_rank\n",
"6527870 2024-06-03 0.523969\n",
" trade_date ma5 ma10 close\n",
"6527870 2024-06-03 10.526 10.216 10.37\n"
]
}
],
"source": [
"\n",
"df['return_5'] = df.groupby('ts_code')['close'].pct_change(periods=5)\n",
"\n",
"df['return_5_rank'] = df.groupby('trade_date')['return_5'].transform(\n",
" lambda x: (x.rank(method='average') - 1) / (x.count() - 1) if x.count() > 1 else 0.5\n",
" )\n",
"\n",
"df['ma5'] = df.groupby('ts_code')['close'].transform(lambda x: x.rolling(window=5, min_periods=1).mean())\n",
"df['ma10'] = df.groupby('ts_code')['close'].transform(lambda x: x.rolling(window=10, min_periods=1).mean())\n",
"\n",
"print(df[(df['ts_code'] == '601117.SH') & (df['trade_date'] == '2024-06-03')][['trade_date', 'return_5_rank']])\n",
"print(df[(df['ts_code'] == '601117.SH') & (df['trade_date'] == '2024-06-03')][['trade_date', 'ma5', 'ma10', 'close']])"
]
},
{
"cell_type": "code",
"execution_count": 3,
@@ -9338,7 +9370,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: 9436343 entries, 0 to 9436342\n",
"RangeIndex: 9456764 entries, 0 to 9456763\n",
"Data columns (total 33 columns):\n",
" # Column Dtype \n",
"--- ------ ----- \n",
@@ -465,7 +465,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 12,
"id": "92d84ce15a562ec6",
"metadata": {
"ExecuteTime": {
@@ -490,17 +490,6 @@
"因子 AR, BR 计算成功。\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"
]
}
],
"source": [
@@ -551,7 +540,7 @@
},
{
"cell_type": "code",
"execution_count": 12,
"execution_count": 13,
"id": "da8d7a30",
"metadata": {},
"outputs": [
@@ -670,7 +659,7 @@
"Calculating cs_rank_size...\n",
"Finished cs_rank_size.\n",
"<class 'pandas.core.frame.DataFrame'>\n",
"RangeIndex: 5087384 entries, 0 to 5087383\n",
"RangeIndex: 5099462 entries, 0 to 5099461\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",
@@ -741,7 +730,7 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": 14,
"id": "b87b938028afa206",
"metadata": {
"ExecuteTime": {
@@ -779,7 +768,7 @@
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": 15,
"id": "f4f16d63ad18d1bc",
"metadata": {
"ExecuteTime": {
@@ -1005,7 +994,7 @@
},
{
"cell_type": "code",
"execution_count": 15,
"execution_count": 16,
"id": "40e6b68a91b30c79",
"metadata": {
"ExecuteTime": {
@@ -1325,7 +1314,7 @@
},
{
"cell_type": "code",
"execution_count": 16,
"execution_count": 17,
"id": "47c12bb34062ae7a",
"metadata": {
"ExecuteTime": {
@@ -1359,7 +1348,7 @@
},
{
"cell_type": "code",
"execution_count": 17,
"execution_count": 18,
"id": "29221dde",
"metadata": {},
"outputs": [
@@ -1402,7 +1391,7 @@
},
{
"cell_type": "code",
"execution_count": 18,
"execution_count": 19,
"id": "03ee5daf",
"metadata": {},
"outputs": [],
@@ -1415,7 +1404,7 @@
},
{
"cell_type": "code",
"execution_count": 19,
"execution_count": 20,
"id": "b76ea08a",
"metadata": {},
"outputs": [
@@ -1424,9 +1413,9 @@
"output_type": "stream",
"text": [
" 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",
"5099459 605599.SH 2026-02-25 14.472051\n",
"5099460 605599.SH 2026-02-26 14.452910\n",
"5099461 605599.SH 2026-02-27 14.472455\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"
@@ -1436,7 +1425,7 @@
"name": "stderr",
"output_type": "stream",
"text": [
"MAD Filtering: 100%|██████████| 131/131 [00:15<00:00, 8.70it/s]\n"
"MAD Filtering: 100%|██████████| 131/131 [00:13<00:00, 9.58it/s]\n"
]
},
{
@@ -1451,7 +1440,7 @@
"name": "stderr",
"output_type": "stream",
"text": [
"MAD Filtering: 100%|██████████| 131/131 [00:15<00:00, 8.47it/s]\n"
"MAD Filtering: 100%|██████████| 131/131 [00:15<00:00, 8.43it/s]\n"
]
},
{
@@ -1491,13 +1480,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-13\n",
"2055886\n",
"df最大日期: 2026-02-27\n",
"2055833\n",
"train_data最小日期: 2020-01-02\n",
"train_data最大日期: 2022-12-30\n",
"2312688\n",
"2324725\n",
"test_data最小日期: 2023-01-03\n",
"test_data最大日期: 2026-02-13\n",
"test_data最大日期: 2026-02-27\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",
@@ -1633,7 +1622,7 @@
},
{
"cell_type": "code",
"execution_count": 20,
"execution_count": 21,
"id": "3ff2d1c5",
"metadata": {},
"outputs": [],
@@ -1774,17 +1763,17 @@
},
{
"cell_type": "code",
"execution_count": 21,
"execution_count": 22,
"id": "a5bbb8be",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<catboost.core.CatBoostClassifier at 0x71335a72d1c0>"
"<catboost.core.CatBoostClassifier at 0x735a75be3050>"
]
},
"execution_count": 21,
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
@@ -1799,7 +1788,7 @@
},
{
"cell_type": "code",
"execution_count": 25,
"execution_count": 26,
"id": "5d1522a7538db91b",
"metadata": {
"ExecuteTime": {
@@ -1838,7 +1827,7 @@
},
{
"cell_type": "code",
"execution_count": 26,
"execution_count": 27,
"id": "09b1799e",
"metadata": {},
"outputs": [
@@ -1860,7 +1849,7 @@
},
{
"cell_type": "code",
"execution_count": 27,
"execution_count": 28,
"id": "e53b209a",
"metadata": {},
"outputs": [
@@ -1868,7 +1857,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"5584 2055886\n",
"5584 2055833\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",
@@ -1876,13 +1865,13 @@
"3 000001.SZ 2023-01-06 0.6162\n",
"4 000001.SZ 2023-01-09 0.5450\n",
"... ... ... ...\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",
"2324720 605599.SH 2026-02-13 1.5153\n",
"2324721 605599.SH 2026-02-24 1.1366\n",
"2324722 605599.SH 2026-02-25 1.2631\n",
"2324723 605599.SH 2026-02-26 0.9249\n",
"2324724 605599.SH 2026-02-27 0.8492\n",
"\n",
"[2312688 rows x 3 columns]\n"
"[2324725 rows x 3 columns]\n"
]
}
],