feat(signals): 新增价格上穿/下穿 MA5 MA10 信号

- 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
This commit is contained in:
shy3130
2026-07-11 13:17:45 +08:00
parent 33212a7d95
commit 56ee0e6c0f
3 changed files with 58 additions and 1 deletions
+27
View File
@@ -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"),
+3 -1
View File
@@ -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": "跌停",
+28
View File
@@ -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日新高',