信义光能问题修复:两层级过滤+趋势检查

Bug 1 — strategy_lifecycle.py: enrich_timing_signal 用 factors[-1] 当信号
  信义光能: base_signal=neutral, factors=[大盘中性,行业偏弱,高估值]
  旧逻辑: factors[-1]='行业偏弱'→成为timing_signal→无效信号
  新逻辑: 先找有效操作方向(买入/加仓/观望/持有/关注/信号不充分),
          找不到→信号不充分。不再从上下文因子里拼凑信号。

Bug 2 — stale_push_wlin.py: 信号过滤太松
  旧逻辑: 只跳过特定关键词(等企稳/关注/信号不充分/持有)
  新逻辑: 信号必须含"买入"或"加仓"才进推荐,其他一律跳过

Check 3 — 趋势检查(新增)
  fetch_trend_data(): 取实时行情+30日K线计算MA排列
  空头排列/弱势震荡→不推荐
  药明康德通过(多头排列+买入信号)  信义光能不通过(空头+行业偏弱)
This commit is contained in:
知微
2026-06-24 14:39:50 +08:00
parent e83dfc415d
commit 8f830b8de2
6 changed files with 351 additions and 106 deletions
Binary file not shown.
+171 -68
View File
@@ -85,17 +85,17 @@
{ {
"code": "000711", "code": "000711",
"name": "ST京蓝", "name": "ST京蓝",
"price": 5.05, "price": 5.06,
"cost": 0, "cost": 0,
"shares": 0, "shares": 0,
"avg_price": 0, "avg_price": 0,
"action": "盈利持有 | ⚠️盈亏比偏低(1:1.7),谨慎买入 | 目标5.38 | 止损4.86 | 买入区4.95~5.07 | 信号:观望", "action": "盈利持有 | ⚠️盈亏比偏低(1:1.6),谨慎买入 | 目标5.38 | 止损4.86 | 买入区4.96~5.07 | 信号:观望",
"stop_loss": 4.86, "stop_loss": 4.86,
"entry_low": 4.95, "entry_low": 4.96,
"entry_high": 5.07, "entry_high": 5.07,
"tech_snapshot": "形态:长影星线/neutral 量价:主动卖盘占优 强撑:4.86 弱撑:4.86 弱压:5.25 强压:5.38", "tech_snapshot": "形态:长影星线/neutral 量价:主动卖盘占优 强撑:4.86 弱撑:4.86 弱压:5.25 强压:5.38",
"timing_signal": "观望", "timing_signal": "观望",
"rr_ratio": 1.74, "rr_ratio": 1.6,
"status": "updated", "status": "updated",
"note": "⚠️盈亏比偏低(1:1.6),谨慎买入", "note": "⚠️盈亏比偏低(1:1.6),谨慎买入",
"timestamp": "2026-06-24 14:23", "timestamp": "2026-06-24 14:23",
@@ -140,12 +140,12 @@
"condition": { "condition": {
"scenario": "weak_consolidation", "scenario": "weak_consolidation",
"price": "<=5.07", "price": "<=5.07",
"price_lower": ">=4.95" "price_lower": ">=4.96"
}, },
"action": { "action": {
"type": "buy", "type": "buy",
"amount": "normal", "amount": "normal",
"limit": 4.95, "limit": 4.96,
"reason": "回调支撑买入" "reason": "回调支撑买入"
}, },
"priority": 1, "priority": 1,
@@ -352,17 +352,17 @@
{ {
"code": "002594", "code": "002594",
"name": "比亚迪", "name": "比亚迪",
"price": 83.45, "price": 83.44,
"cost": 0, "cost": 0,
"shares": 0, "shares": 0,
"avg_price": 0, "avg_price": 0,
"action": "盈利持有 | 目标92.76 | 止损80.95 | 买入区81.78~85.12 | 信号:观望", "action": "盈利持有 | 目标92.76 | 止损80.94 | 买入区81.77~85.11 | 信号:观望",
"stop_loss": 80.95, "stop_loss": 80.94,
"entry_low": 81.78, "entry_low": 81.77,
"entry_high": 85.12, "entry_high": 85.11,
"tech_snapshot": "形态:带下影阴线/neutral 量价:主动卖盘占优 强撑:76.5 弱撑:82.59 弱压:85.0 强压:92.76", "tech_snapshot": "形态:带下影阴线/neutral 量价:主动卖盘占优 强撑:76.5 弱撑:82.58 弱压:85.0 强压:92.76",
"timing_signal": "观望", "timing_signal": "观望",
"rr_ratio": 3.72, "rr_ratio": 3.73,
"status": "updated", "status": "updated",
"note": "", "note": "",
"timestamp": "2026-06-24 14:23", "timestamp": "2026-06-24 14:23",
@@ -389,7 +389,7 @@
{ {
"id": "002594_stop_loss", "id": "002594_stop_loss",
"condition": { "condition": {
"price": "<80.95" "price": "<80.94"
}, },
"action": { "action": {
"type": "sell", "type": "sell",
@@ -406,13 +406,13 @@
"id": "002594_buy_dip", "id": "002594_buy_dip",
"condition": { "condition": {
"scenario": "weak_consolidation", "scenario": "weak_consolidation",
"price": "<=85.12", "price": "<=85.11",
"price_lower": ">=81.78" "price_lower": ">=81.77"
}, },
"action": { "action": {
"type": "buy", "type": "buy",
"amount": "normal", "amount": "normal",
"limit": 81.78, "limit": 81.77,
"reason": "回调支撑买入" "reason": "回调支撑买入"
}, },
"priority": 1, "priority": 1,
@@ -2391,13 +2391,13 @@
"cost": 0, "cost": 0,
"shares": 0, "shares": 0,
"avg_price": 0, "avg_price": 0,
"action": "盈利持有 | 目标180.8 | 止损155.91 | 买入区162.39~168.76", "action": "盈利持有 | 目标180.97 | 止损160.73 | 买入区162.39~168.83",
"stop_loss": 155.91, "stop_loss": 160.73,
"entry_low": 162.39, "entry_low": 162.39,
"entry_high": 168.76, "entry_high": 168.83,
"tech_snapshot": "形态:倒T线/射击之星/bearish 量价:数据不足 强撑:151.2 弱撑:160.9 弱压:168.2 强压:180.8", "tech_snapshot": "形态:带上影阳线/neutral 量价:数据不足 强撑:151.29 弱撑:160.9 弱压:168.47 强压:180.97",
"timing_signal": "行业偏强", "timing_signal": "信号不充分",
"rr_ratio": 3.04, "rr_ratio": 3.07,
"status": "updated", "status": "updated",
"note": "", "note": "",
"timestamp": "2026-06-24 14:24", "timestamp": "2026-06-24 14:24",
@@ -2409,7 +2409,7 @@
"position_advice": "正常配置", "position_advice": "正常配置",
"time_horizon": "数月~1年", "time_horizon": "数月~1年",
"created_at": "2026-06-24 14:24", "created_at": "2026-06-24 14:24",
"take_profit": 180.8, "take_profit": 180.97,
"changelog": [ "changelog": [
{ {
"date": "2026-06-24 14:24", "date": "2026-06-24 14:24",
@@ -2418,7 +2418,110 @@
"reason": "初始策略创建 | 形态:倒T线/射击之星/bearish 量价:数据不足 强撑:151.2 弱撑:160.9 弱压:168.2 强压:18", "reason": "初始策略创建 | 形态:倒T线/射击之星/bearish 量价:数据不足 强撑:151.2 弱撑:160.9 弱压:168.2 强压:18",
"trigger": "初始创建" "trigger": "初始创建"
} }
] ],
"strategy_tree": {
"branches": [
{
"id": "06160_stop_loss",
"condition": {
"price": "<160.73"
},
"action": {
"type": "sell",
"amount": "all",
"reason": "止损"
},
"priority": 0,
"rationale": "止损保护本金",
"trigger_count": 0,
"success_rate": null,
"last_triggered": null
},
{
"id": "06160_buy_dip",
"condition": {
"scenario": "weak_consolidation",
"price": "<=168.83",
"price_lower": ">=162.39"
},
"action": {
"type": "buy",
"amount": "normal",
"limit": 162.39,
"reason": "回调支撑买入"
},
"priority": 1,
"rationale": "价格回调到支撑区,弱势市场低吸",
"trigger_count": 0,
"success_rate": null,
"last_triggered": null
},
{
"id": "06160_breakout_chase",
"condition": {
"scenario": "bullish_recovery",
"price": ">=180.97"
},
"action": {
"type": "buy",
"amount": "normal",
"limit": "market",
"reason": "突破确认追涨"
},
"priority": 2,
"rationale": "价格突破阻力,确认上升趋势后买入",
"trigger_count": 0,
"success_rate": null,
"last_triggered": null
},
{
"id": "06160_trim",
"condition": {
"scenario": "sharp_decline",
"loss_pct": "<-15%"
},
"action": {
"type": "sell",
"amount": "half",
"reason": "急跌降风险"
},
"priority": 3,
"rationale": "急跌市场,深套股减半仓减少敞口",
"trigger_count": 0,
"success_rate": null,
"last_triggered": null
},
{
"id": "06160_take_profit",
"condition": {
"price": ">=180.97"
},
"action": {
"type": "sell",
"amount": "half",
"reason": "止盈锁利"
},
"priority": 4,
"rationale": "达到目标价,减半仓锁定利润",
"trigger_count": 0,
"success_rate": null,
"last_triggered": null
},
{
"id": "06160_hold",
"condition": {},
"action": {
"type": "hold",
"reason": "无明确信号,继续持有"
},
"priority": 99,
"rationale": "没有分支匹配时的默认动作",
"trigger_count": 0,
"success_rate": null,
"last_triggered": null
}
]
}
}, },
{ {
"code": "06869", "code": "06869",
@@ -3191,17 +3294,17 @@
{ {
"code": "300124", "code": "300124",
"name": "汇川技术", "name": "汇川技术",
"price": 66.41, "price": 66.53,
"cost": 0, "cost": 0,
"shares": 0, "shares": 0,
"avg_price": 0, "avg_price": 0,
"action": "盈利持有 | 目标73.17 | 止损64.42 | 买入区65.08~67.74 | 信号:观望", "action": "盈利持有 | 目标73.2 | 止损64.53 | 买入区65.2~67.86 | 信号:观望",
"stop_loss": 64.42, "stop_loss": 64.53,
"entry_low": 65.08, "entry_low": 65.2,
"entry_high": 67.74, "entry_high": 67.86,
"tech_snapshot": "形态:倒T线/射击之星/bearish 量价:主动卖盘占优 强撑:59.93 弱撑:65.6 弱压:67.35 强压:73.17", "tech_snapshot": "形态:长影星线/neutral 量价:主动卖盘占优 强撑:59.96 弱撑:65.68 弱压:67.43 强压:73.2",
"timing_signal": "观望", "timing_signal": "观望",
"rr_ratio": 3.4, "rr_ratio": 3.34,
"status": "updated", "status": "updated",
"note": "", "note": "",
"timestamp": "2026-06-24 14:24", "timestamp": "2026-06-24 14:24",
@@ -3213,7 +3316,7 @@
"position_advice": "减仓或观望", "position_advice": "减仓或观望",
"time_horizon": "观望", "time_horizon": "观望",
"created_at": "2026-06-24 14:24", "created_at": "2026-06-24 14:24",
"take_profit": 73.17, "take_profit": 73.2,
"changelog": [ "changelog": [
{ {
"date": "2026-06-24 14:24", "date": "2026-06-24 14:24",
@@ -3228,7 +3331,7 @@
{ {
"id": "300124_stop_loss", "id": "300124_stop_loss",
"condition": { "condition": {
"price": "<64.42" "price": "<64.53"
}, },
"action": { "action": {
"type": "sell", "type": "sell",
@@ -3245,13 +3348,13 @@
"id": "300124_buy_dip", "id": "300124_buy_dip",
"condition": { "condition": {
"scenario": "weak_consolidation", "scenario": "weak_consolidation",
"price": "<=67.74", "price": "<=67.86",
"price_lower": ">=65.08" "price_lower": ">=65.2"
}, },
"action": { "action": {
"type": "buy", "type": "buy",
"amount": "normal", "amount": "normal",
"limit": 65.08, "limit": 65.2,
"reason": "回调支撑买入" "reason": "回调支撑买入"
}, },
"priority": 1, "priority": 1,
@@ -3264,7 +3367,7 @@
"id": "300124_breakout_chase", "id": "300124_breakout_chase",
"condition": { "condition": {
"scenario": "bullish_recovery", "scenario": "bullish_recovery",
"price": ">=73.17" "price": ">=73.2"
}, },
"action": { "action": {
"type": "buy", "type": "buy",
@@ -3298,7 +3401,7 @@
{ {
"id": "300124_take_profit", "id": "300124_take_profit",
"condition": { "condition": {
"price": ">=73.17" "price": ">=73.2"
}, },
"action": { "action": {
"type": "sell", "type": "sell",
@@ -3990,17 +4093,17 @@
{ {
"code": "601318", "code": "601318",
"name": "中国平安", "name": "中国平安",
"price": 49.1, "price": 49.12,
"cost": 0, "cost": 0,
"shares": 0, "shares": 0,
"avg_price": 0, "avg_price": 0,
"action": "盈利持有 | 目标53.6 | 止损47.63 | 买入区48.12~50.02 | 信号:观望", "action": "盈利持有 | 目标53.61 | 止损47.65 | 买入区48.14~50.03 | 信号:观望",
"stop_loss": 47.63, "stop_loss": 47.65,
"entry_low": 48.12, "entry_low": 48.14,
"entry_high": 50.02, "entry_high": 50.03,
"tech_snapshot": "形态:光头光脚阴线/bearish 量价:主动卖盘占优 强撑:45.74 弱撑:48.46 弱压:50.4 强压:53.6", "tech_snapshot": "形态:光头光脚阴线/bearish 量价:主动卖盘占优 强撑:45.75 弱撑:48.47 弱压:50.4 强压:53.61",
"timing_signal": "观望", "timing_signal": "观望",
"rr_ratio": 3.06, "rr_ratio": 3.05,
"status": "updated", "status": "updated",
"note": "", "note": "",
"timestamp": "2026-06-24 14:24", "timestamp": "2026-06-24 14:24",
@@ -4012,7 +4115,7 @@
"position_advice": "减仓或观望", "position_advice": "减仓或观望",
"time_horizon": "观望", "time_horizon": "观望",
"created_at": "2026-06-24 14:24", "created_at": "2026-06-24 14:24",
"take_profit": 53.6, "take_profit": 53.61,
"changelog": [ "changelog": [
{ {
"date": "2026-06-24 14:24", "date": "2026-06-24 14:24",
@@ -4027,7 +4130,7 @@
{ {
"id": "601318_stop_loss", "id": "601318_stop_loss",
"condition": { "condition": {
"price": "<47.63" "price": "<47.65"
}, },
"action": { "action": {
"type": "sell", "type": "sell",
@@ -4044,13 +4147,13 @@
"id": "601318_buy_dip", "id": "601318_buy_dip",
"condition": { "condition": {
"scenario": "weak_consolidation", "scenario": "weak_consolidation",
"price": "<=50.02", "price": "<=50.03",
"price_lower": ">=48.12" "price_lower": ">=48.14"
}, },
"action": { "action": {
"type": "buy", "type": "buy",
"amount": "normal", "amount": "normal",
"limit": 48.12, "limit": 48.14,
"reason": "回调支撑买入" "reason": "回调支撑买入"
}, },
"priority": 1, "priority": 1,
@@ -4063,7 +4166,7 @@
"id": "601318_breakout_chase", "id": "601318_breakout_chase",
"condition": { "condition": {
"scenario": "bullish_recovery", "scenario": "bullish_recovery",
"price": ">=53.6" "price": ">=53.61"
}, },
"action": { "action": {
"type": "buy", "type": "buy",
@@ -4097,7 +4200,7 @@
{ {
"id": "601318_take_profit", "id": "601318_take_profit",
"condition": { "condition": {
"price": ">=53.6" "price": ">=53.61"
}, },
"action": { "action": {
"type": "sell", "type": "sell",
@@ -4705,17 +4808,17 @@
{ {
"code": "688795", "code": "688795",
"name": "摩尔线程-U", "name": "摩尔线程-U",
"price": 705.0, "price": 704.0,
"cost": 0, "cost": 0,
"shares": 0, "shares": 0,
"avg_price": 0, "avg_price": 0,
"action": "盈利持有 | 目标831.84 | 止损676.81 | 买入区690.9~719.1 | 信号:观望", "action": "盈利持有 | 目标831.51 | 止损676.14 | 买入区689.92~718.08 | 信号:观望",
"stop_loss": 676.81, "stop_loss": 676.14,
"entry_low": 690.9, "entry_low": 689.92,
"entry_high": 719.1, "entry_high": 718.08,
"tech_snapshot": "形态:带下影阳线/neutral 量价:主动卖盘占优 强撑:563.22 弱撑:676.81 弱压:725.39 强压:831.84", "tech_snapshot": "形态:锤子线/T字线/neutral 量价:主动卖盘占优 强撑:563.22 弱撑:676.14 弱压:724.72 强压:831.51",
"timing_signal": "观望", "timing_signal": "观望",
"rr_ratio": 4.5, "rr_ratio": 4.58,
"status": "updated", "status": "updated",
"note": "", "note": "",
"timestamp": "2026-06-24 14:24", "timestamp": "2026-06-24 14:24",
@@ -4727,7 +4830,7 @@
"position_advice": "正常配置", "position_advice": "正常配置",
"time_horizon": "数月~1年", "time_horizon": "数月~1年",
"created_at": "2026-06-24 14:24", "created_at": "2026-06-24 14:24",
"take_profit": 831.84, "take_profit": 831.51,
"changelog": [ "changelog": [
{ {
"date": "2026-06-24 14:24", "date": "2026-06-24 14:24",
@@ -4742,7 +4845,7 @@
{ {
"id": "688795_stop_loss", "id": "688795_stop_loss",
"condition": { "condition": {
"price": "<676.81" "price": "<676.14"
}, },
"action": { "action": {
"type": "sell", "type": "sell",
@@ -4759,13 +4862,13 @@
"id": "688795_buy_dip", "id": "688795_buy_dip",
"condition": { "condition": {
"scenario": "weak_consolidation", "scenario": "weak_consolidation",
"price": "<=719.1", "price": "<=718.08",
"price_lower": ">=690.9" "price_lower": ">=689.92"
}, },
"action": { "action": {
"type": "buy", "type": "buy",
"amount": "normal", "amount": "normal",
"limit": 690.9, "limit": 689.92,
"reason": "回调支撑买入" "reason": "回调支撑买入"
}, },
"priority": 1, "priority": 1,
@@ -4778,7 +4881,7 @@
"id": "688795_breakout_chase", "id": "688795_breakout_chase",
"condition": { "condition": {
"scenario": "bullish_recovery", "scenario": "bullish_recovery",
"price": ">=831.84" "price": ">=831.51"
}, },
"action": { "action": {
"type": "buy", "type": "buy",
@@ -4812,7 +4915,7 @@
{ {
"id": "688795_take_profit", "id": "688795_take_profit",
"condition": { "condition": {
"price": ">=831.84" "price": ">=831.51"
}, },
"action": { "action": {
"type": "sell", "type": "sell",
@@ -5028,5 +5131,5 @@
} }
], ],
"total": 39, "total": 39,
"regenerated_at": "2026-06-24 14:25" "regenerated_at": "2026-06-24 14:37"
} }
+69 -23
View File
@@ -25,7 +25,9 @@
"rr_ratio": 0.51, "rr_ratio": 0.51,
"action_note": "深套持有", "action_note": "深套持有",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 8.52,
"change_pct": -0.23
}, },
{ {
"code": "600563", "code": "600563",
@@ -52,7 +54,9 @@
"rr_ratio": 3.54, "rr_ratio": 3.54,
"action_note": "", "action_note": "",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 178.76,
"change_pct": 10.0
}, },
{ {
"code": "601899", "code": "601899",
@@ -79,7 +83,9 @@
"rr_ratio": 0.71, "rr_ratio": 0.71,
"action_note": "深套持有", "action_note": "深套持有",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 27.59,
"change_pct": -0.58
}, },
{ {
"code": "603259", "code": "603259",
@@ -106,7 +112,9 @@
"rr_ratio": 3.44, "rr_ratio": 3.44,
"action_note": "", "action_note": "",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 115.11,
"change_pct": 8.28
}, },
{ {
"code": "688411", "code": "688411",
@@ -133,7 +141,9 @@
"rr_ratio": 0.98, "rr_ratio": 0.98,
"action_note": "⚠️盈亏比偏低(1:1.0),不建议加仓", "action_note": "⚠️盈亏比偏低(1:1.0),不建议加仓",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 266.44,
"change_pct": -2.13
}, },
{ {
"code": "688639", "code": "688639",
@@ -160,7 +170,9 @@
"rr_ratio": 1.09, "rr_ratio": 1.09,
"action_note": "⚠️盈亏比偏低(1:1.1),不建议加仓", "action_note": "⚠️盈亏比偏低(1:1.1),不建议加仓",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 21.43,
"change_pct": -1.83
}, },
{ {
"code": "688981", "code": "688981",
@@ -187,7 +199,9 @@
"rr_ratio": 2.34, "rr_ratio": 2.34,
"action_note": "", "action_note": "",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 151.59,
"change_pct": 6.98
}, },
{ {
"code": "000700", "code": "000700",
@@ -214,7 +228,9 @@
"rr_ratio": 3.83, "rr_ratio": 3.83,
"action_note": "", "action_note": "",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 14.5,
"change_pct": -3.2
}, },
{ {
"code": "001309", "code": "001309",
@@ -241,7 +257,9 @@
"rr_ratio": 0.03, "rr_ratio": 0.03,
"action_note": "⚠️盈亏比偏低(1:0.5),不建议加仓", "action_note": "⚠️盈亏比偏低(1:0.5),不建议加仓",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 803.93,
"change_pct": 6.48
}, },
{ {
"code": "300035", "code": "300035",
@@ -268,7 +286,9 @@
"rr_ratio": 0.98, "rr_ratio": 0.98,
"action_note": "深套持有", "action_note": "深套持有",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 16.02,
"change_pct": -2.08
}, },
{ {
"code": "300548", "code": "300548",
@@ -295,7 +315,9 @@
"rr_ratio": 5.93, "rr_ratio": 5.93,
"action_note": "短炒强趋势持", "action_note": "短炒强趋势持",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 280.8,
"change_pct": -1.83
}, },
{ {
"code": "300750", "code": "300750",
@@ -322,7 +344,9 @@
"rr_ratio": 0.9, "rr_ratio": 0.9,
"action_note": "⚠️盈亏比偏低(1:0.9),不建议加仓", "action_note": "⚠️盈亏比偏低(1:0.9),不建议加仓",
"timing_signal": "弱势持有" "timing_signal": "弱势持有"
} },
"price": 395.88,
"change_pct": 0.86
}, },
{ {
"code": "00700", "code": "00700",
@@ -349,7 +373,9 @@
"rr_ratio": 0.95, "rr_ratio": 0.95,
"action_note": "⚠️盈亏比偏低(1:1.0),不建议加仓", "action_note": "⚠️盈亏比偏低(1:1.0),不建议加仓",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 430.0,
"change_pct": 3.66
}, },
{ {
"code": "00981", "code": "00981",
@@ -376,7 +402,9 @@
"rr_ratio": 3.21, "rr_ratio": 3.21,
"action_note": "", "action_note": "",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 84.45,
"change_pct": 8.48
}, },
{ {
"code": "01088", "code": "01088",
@@ -403,7 +431,9 @@
"rr_ratio": 0.92, "rr_ratio": 0.92,
"action_note": "⚠️盈亏比偏低(1:0.9),不建议加仓", "action_note": "⚠️盈亏比偏低(1:0.9),不建议加仓",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 41.86,
"change_pct": -0.33
}, },
{ {
"code": "01211", "code": "01211",
@@ -430,7 +460,9 @@
"rr_ratio": 0.95, "rr_ratio": 0.95,
"action_note": "深套持有", "action_note": "深套持有",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 76.1,
"change_pct": 0.33
}, },
{ {
"code": "01478", "code": "01478",
@@ -457,7 +489,9 @@
"rr_ratio": 0.99, "rr_ratio": 0.99,
"action_note": "深套持有", "action_note": "深套持有",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 7.7,
"change_pct": -2.28
}, },
{ {
"code": "01888", "code": "01888",
@@ -484,7 +518,9 @@
"rr_ratio": 7.36, "rr_ratio": 7.36,
"action_note": "短炒强趋势持", "action_note": "短炒强趋势持",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 94.6,
"change_pct": 8.42
}, },
{ {
"code": "02202", "code": "02202",
@@ -511,7 +547,9 @@
"rr_ratio": 1.11, "rr_ratio": 1.11,
"action_note": "深套持有", "action_note": "深套持有",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 2.35,
"change_pct": -1.67
}, },
{ {
"code": "02318", "code": "02318",
@@ -538,7 +576,9 @@
"rr_ratio": 14.89, "rr_ratio": 14.89,
"action_note": "⚠️盈亏比偏低(1:1.0),不建议加仓", "action_note": "⚠️盈亏比偏低(1:1.0),不建议加仓",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 52.75,
"change_pct": -1.59
}, },
{ {
"code": "02388", "code": "02388",
@@ -565,7 +605,9 @@
"rr_ratio": 2.45, "rr_ratio": 2.45,
"action_note": "", "action_note": "",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 46.78,
"change_pct": -0.47
}, },
{ {
"code": "06869", "code": "06869",
@@ -592,7 +634,9 @@
"rr_ratio": 7.68, "rr_ratio": 7.68,
"action_note": "短炒强趋势持", "action_note": "短炒强趋势持",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 264.8,
"change_pct": 0.08
}, },
{ {
"code": "09868", "code": "09868",
@@ -619,7 +663,9 @@
"rr_ratio": 21.64, "rr_ratio": 21.64,
"action_note": "⚠️盈亏比偏低(1:1.0),不建议加仓", "action_note": "⚠️盈亏比偏低(1:1.0),不建议加仓",
"timing_signal": "持有" "timing_signal": "持有"
} },
"price": 49.5,
"change_pct": 0.28
} }
], ],
"cash": 20371, "cash": 20371,
+5 -5
View File
@@ -108,7 +108,7 @@
"date": "2026-06-24", "date": "2026-06-24",
"high": 88.32, "high": 88.32,
"low": 82.78, "low": 82.78,
"close": 83.45 "close": 83.44
} }
], ],
"00700": [ "00700": [
@@ -1004,7 +1004,7 @@
"date": "2026-06-24", "date": "2026-06-24",
"high": 168.6, "high": 168.6,
"low": 160.0, "low": 160.0,
"close": 165.6 "close": 166.0
} }
], ],
"06869": [ "06869": [
@@ -1284,7 +1284,7 @@
"date": "2026-06-24", "date": "2026-06-24",
"high": 68.8, "high": 68.8,
"low": 65.74, "low": 65.74,
"close": 66.41 "close": 66.52
} }
], ],
"300548": [ "300548": [
@@ -2316,7 +2316,7 @@
"date": "2026-06-24", "date": "2026-06-24",
"high": 745.2, "high": 745.2,
"low": 660.01, "low": 660.01,
"close": 705.0 "close": 704.0
} }
], ],
"688802": [ "688802": [
@@ -2610,7 +2610,7 @@
"date": "2026-06-24", "date": "2026-06-24",
"high": 52.43, "high": 52.43,
"low": 49.03, "low": 49.03,
"close": 49.1 "close": 49.12
} }
], ],
"002171": [ "002171": [
+92 -6
View File
@@ -27,6 +27,72 @@ except ImportError:
sys.path.insert(0, "/home/hmo/MoFin/scripts") sys.path.insert(0, "/home/hmo/MoFin/scripts")
from stock_scorer import score_future_outlook, is_hk_stock, settlement_delay_note from stock_scorer import score_future_outlook, is_hk_stock, settlement_delay_note
# ── 趋势检查 ────────────────────────────────────────────────────
def fetch_trend_data(code):
"""取均线数据判断趋势状态。返回 (current_price, ma5, trend_label) 或 None"""
try:
prefix = "sh" if code.startswith(('60','68','51','56','50')) else "sz" if code.startswith(('00','30','15')) else "hk"
url = f"http://qt.gtimg.cn/q={prefix}{code}"
req = Request(url, headers={'User-Agent': 'Mozilla/5.0'})
resp = urlopen(req, timeout=5).read().decode('gbk')
fld = resp.split('=')[1].strip().strip('"').strip(';').split('~')
current = float(fld[3]) if len(fld) > 3 else 0
except:
return None
try:
url = f"http://ifzq.gtimg.cn/appstock/app/fqkline/get?param={prefix}{code},day,,,30,qfq"
req = Request(url, headers={'User-Agent': 'Mozilla/5.0'})
resp = urlopen(req, timeout=5).read().decode('utf-8')
data = json.loads(resp)
day_key = 'qfqday' if prefix != 'hk' else 'day'
bars = data.get('data', {}).get(f'{prefix}{code}', {}).get(day_key, [])
except:
return None
if not bars or current <= 0:
return None
closes = [float(b[2]) for b in bars]
if len(closes) < 5:
return None
def ma(n):
return sum(closes[-n:]) / n
ma5 = ma(5)
ma10 = ma(10) if len(closes) >= 10 else None
ma20 = ma(20) if len(closes) >= 20 else None
# 趋势分析
pct_above_ma5 = (current - ma5) / ma5 * 100
uptrend = False
if ma20 and ma10:
if ma5 > ma10 > ma20:
trend_label = "多头排列"
uptrend = True
elif current < ma5 and ma5 < ma10 and current < ma10:
trend_label = "空头排列"
elif current > ma5 and ma5 > ma10:
trend_label = "短期转强"
uptrend = True
else:
trend_label = "震荡"
if current > ma5 > ma10:
uptrend = True
else:
trend_label = "数据不足"
return {
'price': current,
'ma5': round(ma5, 2),
'ma10': round(ma10, 2) if ma10 else None,
'ma20': round(ma20, 2) if ma20 else None,
'pct_above_ma5': round(pct_above_ma5, 1),
'trend': trend_label,
'uptrend': uptrend,
}
# ── XMPP
XMPP_BRIDGE = "http://127.0.0.1:5805/" XMPP_BRIDGE = "http://127.0.0.1:5805/"
XMPP_USER = "hmo@yoin.fun" XMPP_USER = "hmo@yoin.fun"
@@ -278,10 +344,11 @@ def main():
-code_data.get(s[1], {}).get("rr_ratio", 0) -code_data.get(s[1], {}).get("rr_ratio", 0)
)) ))
# 只展示有清晰操作信号的个股:不含"等企稳""关注""信号不充分""neutral"及纯持有信号 # 只展示有清晰操作信号的个股
SKIP_KEYWORDS = ["等企稳", "关注", "信号不充分"] # timing_signal 必须是明确操作方向:买入/加仓/观望/关注/信号不充分
# 行业描述(行业偏弱/行业偏强/大盘变盘等)不是操作信号,一律跳过
BUY_KEYWORDS = ["买入", "加仓"] VALID_SIGNALS = {"买入", "加仓", "观望", "关注", "信号不充分"}
SKIP_KEYWORDS = ["等企稳", "信号不充分"]
actionable = [] actionable = []
for s in stocks: for s in stocks:
@@ -292,9 +359,19 @@ def main():
if any(kw in sig for kw in SKIP_KEYWORDS): if any(kw in sig for kw in SKIP_KEYWORDS):
continue continue
# 中性信号跳过 # 中性信号跳过
stripped = sig.strip().lower() stripped = sig.strip()
if not stripped or stripped in ("", "neutral", "持有", "深套持有", "弱势持有"): if not stripped or stripped.lower() in ("", "neutral", "持有", "深套持有", "弱势持有"):
continue continue
# 信号必须含买入/加仓才推荐——其他非操作信号跳过
if not any(kw in sig for kw in ["买入", "加仓"]):
continue
# 趋势检查:必须不是空头排列(价格在MA5以下且MA5<MA10
trend = fetch_trend_data(s[1])
if trend:
if not trend['uptrend']:
# 空头排列或弱势震荡,不推荐
continue
# (如果趋势数据获取失败,放行—不因数据问题错杀)
actionable.append(s) actionable.append(s)
if not actionable: if not actionable:
@@ -613,6 +690,15 @@ def main():
cooled, elapsed, cd_key = in_cooldown(code, branch_action, cooldown) cooled, elapsed, cd_key = in_cooldown(code, branch_action, cooldown)
if cooled: if cooled:
continue continue
# 策略质量过滤:只有正向/中性信号才推操作建议
bad_keywords = ["偏弱", "弱势", "观望", "卖出", "回避", "回避"]
if any(kw in sig for kw in bad_keywords):
continue
# 行业背景过滤:行业大跌时不在买入区推荐(即使个股信号好)
if "大跌" in sector:
continue
# 换仓评估:现金不足时评估是否卖差票换推荐股 # 换仓评估:现金不足时评估是否卖差票换推荐股
swap_text = None swap_text = None
+14 -4
View File
@@ -1141,10 +1141,20 @@ def enrich_timing_signal(base_signal, macro_desc="", sector_note="",
if not factors: if not factors:
return "信号不充分", [] return "信号不充分", []
# 修改:信号保持干净(只取base_signal),不把全部因子拼进去 # 信号只应包含明确的买卖方向,不能从行业/大盘等上下文因子拼
# enriched 仍作为完整的可读描述保留在 factors_list 中 # base_signal 存在且非 neutral → 用 base_signal
# 调用方决定是否展示 factors # 否则 → 信号不充分(不拿 factors[-1] 当信号)
clean_signal = base_signal if base_signal and base_signal != "neutral" else factors[-1] if base_signal and base_signal != "neutral":
clean_signal = base_signal
else:
# 从 factors 中找第一个有效的操作方向信号
valid_direction = {"买入", "加仓", "观望", "持有", "关注", "信号不充分"}
signal_found = ""
for f in reversed(factors):
if f in valid_direction:
signal_found = f
break
clean_signal = signal_found if signal_found else "信号不充分"
return clean_signal, factors return clean_signal, factors