From 56ee0e6c0f5eb57c4de1014dddb6885656d42a25 Mon Sep 17 00:00:00 2001 From: shy3130 Date: Sat, 11 Jul 2026 13:17:45 +0800 Subject: [PATCH] =?UTF-8?q?feat(signals):=20=E6=96=B0=E5=A2=9E=E4=BB=B7?= =?UTF-8?q?=E6=A0=BC=E4=B8=8A=E7=A9=BF/=E4=B8=8B=E7=A9=BF=20MA5=20MA10=20?= =?UTF-8?q?=E4=BF=A1=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - pipeline.py: compute_signals() 与 compute_enriched_today() 双路径 新增 signal_ma5_breakout/breakdown、signal_ma10_breakout/breakdown (盘中路径同步补 _prev_ma10 到 sig_prev) - ENRICHED_COLUMNS 登记新列 - signals.ts: BUILTIN_SIGNAL_DEFINITIONS 加 4 条定义 - monitor.py: _SIGNAL_CN 加 4 条中文标签 注: 价格上穿/下穿 MA20 已有 (signal_ma20_breakout/breakdown), 本次补齐 MA5/MA10 --- backend/app/indicators/pipeline.py | 27 +++++++++++++++++++++++++++ backend/app/strategy/monitor.py | 4 +++- frontend/src/lib/signals.ts | 28 ++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/backend/app/indicators/pipeline.py b/backend/app/indicators/pipeline.py index f7b27b9..084c8b5 100644 --- a/backend/app/indicators/pipeline.py +++ b/backend/app/indicators/pipeline.py @@ -144,6 +144,10 @@ ENRICHED_COLUMNS: dict[str, dict[str, str]] = { "signal_macd_dead": "MACD死叉 (DIF下穿DEA)", "signal_ma20_breakout": "收盘突破MA20上方", "signal_ma20_breakdown": "收盘跌破MA20下方", + "signal_ma5_breakout": "收盘突破MA5上方", + "signal_ma5_breakdown": "收盘跌破MA5下方", + "signal_ma10_breakout": "收盘突破MA10上方", + "signal_ma10_breakdown": "收盘跌破MA10下方", "signal_n_day_high": "创60日新高", "signal_n_day_low": "创60日新低", "signal_boll_breakout_upper": "突破布林上轨", @@ -567,6 +571,18 @@ def compute_signals(df: pl.DataFrame) -> pl.DataFrame: ((pl.col("close") < pl.col("ma20")) & (pl.col("close").shift(1).over("symbol") >= pl.col("ma20").shift(1).over("symbol"))) .alias("signal_ma20_breakdown"), + ((pl.col("close") > pl.col("ma5")) & + (pl.col("close").shift(1).over("symbol") <= pl.col("ma5").shift(1).over("symbol"))) + .alias("signal_ma5_breakout"), + ((pl.col("close") < pl.col("ma5")) & + (pl.col("close").shift(1).over("symbol") >= pl.col("ma5").shift(1).over("symbol"))) + .alias("signal_ma5_breakdown"), + ((pl.col("close") > pl.col("ma10")) & + (pl.col("close").shift(1).over("symbol") <= pl.col("ma10").shift(1).over("symbol"))) + .alias("signal_ma10_breakout"), + ((pl.col("close") < pl.col("ma10")) & + (pl.col("close").shift(1).over("symbol") >= pl.col("ma10").shift(1).over("symbol"))) + .alias("signal_ma10_breakdown"), (pl.col("close") >= pl.col("high_60d")).alias("signal_n_day_high"), (pl.col("close") <= pl.col("low_60d")).alias("signal_n_day_low"), (pl.col("close") > pl.col("boll_upper")).alias("signal_boll_breakout_upper"), @@ -1432,6 +1448,7 @@ def compute_enriched_today( sig_prev = prev_enriched.select( "symbol", pl.col("ma5").alias("_prev_ma5"), + pl.col("ma10").alias("_prev_ma10"), pl.col("ma20").alias("_prev_ma20"), pl.col("ma60").alias("_prev_ma60"), pl.col("macd_dif").alias("_prev_dif"), @@ -1460,6 +1477,16 @@ def compute_enriched_today( .alias("signal_ma20_breakout"), ((pl.col("close") < pl.col("ma20")) & (pl.col("_prev_close_enriched") >= pl.col("_prev_ma20"))) .alias("signal_ma20_breakdown"), + # MA5 突破/跌破 + ((pl.col("close") > pl.col("ma5")) & (pl.col("_prev_close_enriched") <= pl.col("_prev_ma5"))) + .alias("signal_ma5_breakout"), + ((pl.col("close") < pl.col("ma5")) & (pl.col("_prev_close_enriched") >= pl.col("_prev_ma5"))) + .alias("signal_ma5_breakdown"), + # MA10 突破/跌破 + ((pl.col("close") > pl.col("ma10")) & (pl.col("_prev_close_enriched") <= pl.col("_prev_ma10"))) + .alias("signal_ma10_breakout"), + ((pl.col("close") < pl.col("ma10")) & (pl.col("_prev_close_enriched") >= pl.col("_prev_ma10"))) + .alias("signal_ma10_breakdown"), # BOLL 突破 (pl.col("close") >= pl.col("boll_upper")).alias("signal_boll_breakout_upper"), (pl.col("close") <= pl.col("boll_lower")).alias("signal_boll_breakdown_lower"), diff --git a/backend/app/strategy/monitor.py b/backend/app/strategy/monitor.py index bdb8902..6ebcf18 100644 --- a/backend/app/strategy/monitor.py +++ b/backend/app/strategy/monitor.py @@ -33,7 +33,9 @@ _SIGNAL_CN: dict[str, str] = { "signal_ma_golden_5_20": "MA5上穿MA20", "signal_ma_dead_5_20": "MA5下穿MA20", "signal_ma_golden_20_60": "MA20上穿MA60", "signal_macd_golden": "MACD金叉", "signal_macd_dead": "MACD死叉", "signal_ma20_breakout": "突破MA20", - "signal_ma20_breakdown": "跌破MA20", "signal_n_day_high": "60日新高", + "signal_ma20_breakdown": "跌破MA20", "signal_ma5_breakout": "突破MA5", + "signal_ma5_breakdown": "跌破MA5", "signal_ma10_breakout": "突破MA10", + "signal_ma10_breakdown": "跌破MA10", "signal_n_day_high": "60日新高", "signal_n_day_low": "60日新低", "signal_boll_breakout_upper": "突破布林上轨", "signal_boll_breakdown_lower": "跌破布林下轨", "signal_volume_surge": "放量", "signal_limit_up": "涨停", "signal_limit_down": "跌停", diff --git a/frontend/src/lib/signals.ts b/frontend/src/lib/signals.ts index eff1b76..da5207b 100644 --- a/frontend/src/lib/signals.ts +++ b/frontend/src/lib/signals.ts @@ -66,6 +66,34 @@ export const BUILTIN_SIGNAL_DEFINITIONS: BuiltinSignalDefinition[] = [ category: '趋势', description: '收盘价向下跌破 MA20,常用于趋势破位卖点。', }, + { + id: 'signal_ma5_breakout', + name: '突破MA5', + kind: 'entry', + category: '趋势', + description: '收盘价向上突破 MA5,偏短线转强或回踩企稳买点。', + }, + { + id: 'signal_ma5_breakdown', + name: '跌破MA5', + kind: 'exit', + category: '趋势', + description: '收盘价向下跌破 MA5,偏短线转弱或止盈止损卖点。', + }, + { + id: 'signal_ma10_breakout', + name: '突破MA10', + kind: 'entry', + category: '趋势', + description: '收盘价向上突破 MA10,偏短中线转强或突破买点。', + }, + { + id: 'signal_ma10_breakdown', + name: '跌破MA10', + kind: 'exit', + category: '趋势', + description: '收盘价向下跌破 MA10,偏短中线转弱或破位卖点。', + }, { id: 'signal_n_day_high', name: '60日新高',