efactor(qmt): 重构架构 - 统一信号发送和消息处理
- 修复 qmt_engine.py 中 initialize() 的重复代码 - 新增 message_processor.py: Redis Stream 消息处理器 - 新增 logger.py: 细粒度日志模块 - 新增 qmt_sender.py: 统一信号发送端(槽位+百分比模式) - 新增 backtest_consumer.py: 回测消息消费者 - 删除旧模块: qmt_trader.py, qmt_signal_sender.py, qmt_percentage_sender.py - 更新文档: qmt_functionality.md 反映新架构
This commit is contained in:
@@ -433,7 +433,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"execution_count": 11,
|
||||
"id": "85c3e3d0235ffffa",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
@@ -446,12 +446,12 @@
|
||||
"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",
|
||||
"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",
|
||||
@@ -465,7 +465,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"execution_count": null,
|
||||
"id": "92d84ce15a562ec6",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
@@ -546,7 +546,140 @@
|
||||
"df = add_financial_factor(df, fina_indicator_df, factor_value_col='roe')\n",
|
||||
"\n",
|
||||
"calculate_arbr(df, N=26)\n",
|
||||
"df['log_circ_mv'] = np.log(df['circ_mv'])\n",
|
||||
"df['log_circ_mv'] = np.log(df['circ_mv'])\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"id": "da8d7a30",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"使用 'ann_date' 作为财务数据生效日期。\n",
|
||||
"使用 'ann_date' 作为财务数据生效日期。\n",
|
||||
"使用 'ann_date' 作为财务数据生效日期。\n",
|
||||
"使用 'ann_date' 作为财务数据生效日期。\n",
|
||||
"警告: 从 financial_data_subset 中移除了 15 行,因为其 '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: 5087384 entries, 0 to 5087383\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"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"df = calculate_cashflow_to_ev_factor(df, cashflow_df, balancesheet_df)\n",
|
||||
"df = caculate_book_to_price_ratio(df, fina_indicator_df)\n",
|
||||
"\n",
|
||||
@@ -608,7 +741,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 13,
|
||||
"id": "b87b938028afa206",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
@@ -646,7 +779,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 14,
|
||||
"id": "f4f16d63ad18d1bc",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
@@ -872,7 +1005,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 15,
|
||||
"id": "40e6b68a91b30c79",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
@@ -1192,7 +1325,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 16,
|
||||
"id": "47c12bb34062ae7a",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
@@ -1226,7 +1359,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 17,
|
||||
"id": "29221dde",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
@@ -1269,7 +1402,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 18,
|
||||
"id": "03ee5daf",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -1282,7 +1415,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 19,
|
||||
"id": "b76ea08a",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
@@ -1303,7 +1436,7 @@
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"MAD Filtering: 100%|██████████| 131/131 [00:13<00:00, 9.90it/s]\n"
|
||||
"MAD Filtering: 100%|██████████| 131/131 [00:15<00:00, 8.70it/s]\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1318,7 +1451,7 @@
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"MAD Filtering: 100%|██████████| 131/131 [00:14<00:00, 8.90it/s]\n"
|
||||
"MAD Filtering: 100%|██████████| 131/131 [00:15<00:00, 8.47it/s]\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1500,7 +1633,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 20,
|
||||
"id": "3ff2d1c5",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -1641,17 +1774,17 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 21,
|
||||
"id": "a5bbb8be",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"<catboost.core.CatBoostClassifier at 0x752dd29c0e30>"
|
||||
"<catboost.core.CatBoostClassifier at 0x71335a72d1c0>"
|
||||
]
|
||||
},
|
||||
"execution_count": 19,
|
||||
"execution_count": 21,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
@@ -1666,7 +1799,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 25,
|
||||
"id": "5d1522a7538db91b",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
@@ -1705,7 +1838,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 26,
|
||||
"id": "09b1799e",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
@@ -1727,7 +1860,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 27,
|
||||
"id": "e53b209a",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
@@ -1775,7 +1908,7 @@
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.13.2"
|
||||
"version": "3.12.11"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
||||
Reference in New Issue
Block a user