硬性策略质量门禁 validate_strategy()

新增 STRATEGY_QUALITY_GATES 检查清单(9条红线):
CRITICAL: 止损/止盈存在+>0, 买入区下沿<上沿
HIGH: 止损≤买入区, 买入推荐含RR≥1.5, 港股标currency=HKD
MEDIUM: signal短词, tech_snapshot含技术位

enforce_strategy_quality() 插在写入链的两处:
1. reassess_with_context() return前 → 单只重评必过
2. regenerate_all() for d in decisions: 写DB前 → 批量重评必过

不过的:status=review_needed, signal降级→信号不充分
不会写进DB/JSON,除非修复了CRITICAL问题
This commit is contained in:
知微
2026-07-02 13:46:53 +08:00
parent 04b8a6d4bc
commit 7c0e85af28
32 changed files with 12496 additions and 75159 deletions
Binary file not shown.
Binary file not shown.
+66
View File
@@ -1,5 +1,22 @@
记录知微对MoFin系统的缺陷修复和知识萃取项。 记录知微对MoFin系统的缺陷修复和知识萃取项。
## 2026-07-02 11:30 macro_context_collector.py Pattern 9 百分比阈值修复 + 跨句涨幅匹配修复
**发现了什么:** 自愈执行器报告false positive——"中概领涨"被标记为HIGH风险。追踪发现Pattern 9 `指数[^。]*?(?:跌幅|下跌)[^。]*?[2-9]%`有两个Bug
1. 小数阈值Bug: `[2-9]%`在"0.3%"中提取"3%"匹配,误将<2%跌幅标为HIGH
2. 跨句匹配Bug: "指数集体下跌的背景下...中概收涨近3%"中,`[^。]*?`跨过整个句子把"下跌"和"3%"连起来,但"下跌"是指美股下跌,"3%"是指中概收涨——两个不同语境
**修改了什么:**
- 文件: `/home/hmo/MoFin/scripts/macro_context_collector.py`
- Pattern 9: `指数[^。]*?(?:跌幅|下跌)[^。]*?[2-9]%`
`指数[^。]*?(?:跌幅[^。]{0,20}(?:扩大至|达|至|超|为|逾)[^。]*?(?<![0-9.])(?:[2-9]|[1-9][0-9])(?:\.\d+)?%|下跌(?!.*?涨)[^。]*?(?<![0-9.])(?:[2-9]|[1-9][0-9])(?:\.\d+)?%)`
- "跌幅"分支:要求跌幅后有测量词(扩大至/达/至/超/为/逾),防止"跌幅"和其他分句的"%"跨句匹配
- "下跌"分支:用`(?!.*?涨)`负向前瞻阻断含有"涨"的上下文(如"收涨近3%"
- 阈值修复:`(?<![0-9.])(?:[2-9]|[1-9][0-9])(?:\.\d+)?%` 防止"0.3%"中"3%"被提取
- Pattern 10: `(?:暴跌|重挫|熔断).*[5-9]%` → 同样加小数排除 + 改成`[5-9]|[1-9][0-9]`范围
- `_PATTERN_CHECKS``_KNOWN_BAD_SIGS`同步更新
- `intraday_health_check.py`: 宏观风险HIGH去重,防止同一风险状态累积多个TODO
## 2026-06-23 09:00 数据采集脚本修复 ## 2026-06-23 09:00 数据采集脚本修复
**发现了什么:** `market_watch.py` cron任务报错,exit code 1 **发现了什么:** `market_watch.py` cron任务报错,exit code 1
@@ -132,3 +149,52 @@
- 严禁从 multi_tf_cache.json / decisions.json 等缓存文件直接读取价格数据来推操作建议 - 严禁从 multi_tf_cache.json / decisions.json 等缓存文件直接读取价格数据来推操作建议
- 唯一允许的价格源:腾讯实时 APIqt.gtimg.cn)或 price_monitor 刚写入的 events/state - 唯一允许的价格源:腾讯实时 APIqt.gtimg.cn)或 price_monitor 刚写入的 events/state
- 违反这条 → 自动回滚,追加到违规记录 - 违反这条 → 自动回滚,追加到违规记录
## 2026-07-02 10:00 盘中自检 NameError 修复
**发现了什么:** 自愈执行器报 `盘中自检: 价格数据新鲜度检查失败: name 'mo_data' is not defined`
- 根因:`intraday_health_check.py` 第11行用 `from mo_data import read_portfolio`(直接导入函数),但第117行写的是 `mo_data.read_portfolio()`(当模块名调用)
**修改了什么:**
- 文件:`/home/hmo/MoFin/scripts/intraday_health_check.py`
- 变更:`mo_data.read_portfolio()` → `read_portfolio()`
**效果预期:** 盘中自检不再因这个 NameError 报异常,能正常检查 portfolio.json 数据新鲜度。
## 2026-07-02 10:51 宏观风险HIGH升级应对
**发现了什么:** 自愈执行器上报当日第二次HIGH信号(科创50扩大至-5%、创业板-4%)。同时KOSPI从-7%收窄至-3%(改善方向信号)。
**修改了什么:**
- 文件:`macro_risk_state.json`
- 变更:升级模式更新state,分别标注恶化(科创50/创业板扩大跌幅)和改善(KOSPI收窄、恒指+1.3%)两个方向,避免笼统"附加新数据点"
**萃取知识:**
1. B类板块冲击下,防御仓位(紫金+6.8%、黄金ETF+2%、神华+1.2%)当日有效对冲科技股损失,验证了组合构建合理性
2. 中芯国际A(688981)是当日最危险持仓(距止损2.14%),中芯国际AH走势分化(A-2.96% vs H-8.05%)值得关注——A股有溢价保护,H股更直接暴露于全球半导体卖压
3. 分歧检测bias=opportunity + A/H科技背离>5pp → 极端背离时不能简单看空,A股科技暴跌时港股科技反而上涨,资金在跨市场迁移而非逃离科技板块
## 2026-07-02 盘中 价格数据新鲜度检查格式不兼容
**发现了什么:** 自愈执行器报 `盘中自检: 价格数据新鲜度检查失败: unconverted data remains: :06`
**根因:** `intraday_health_check.py` 的 `datetime.strptime(pf_updated, "%Y-%m-%d %H:%M:%S")` 硬编码要求带秒格式,但 `price_monitor.py` 等写入 `updated_at` 用 `strftime('%Y-%m-%d %H:%M')` 无秒格式。当 `read_portfolio()` 回退到 JSON 冷备时读到无秒时间戳 → 解析失败。
**修改了什么:**
- 文件:`/home/hmo/MoFin/scripts/intraday_health_check.py`
- 变更:引入 `_parse_updated_at()` 函数,先试带秒格式 `%Y-%m-%d %H:%M:%S`,失败则回退无秒格式 `%Y-%m-%d %H:%M`;两次都失败时明确记录"格式无法解析"而非抛异常
**效果预期:** 无论 `updated_at` 是 `'2026-07-02 10:43'`(无秒)还是 `'2026-07-02 10:43:53'`(有秒),都能正确解析并计算新鲜度。
## 2026-07-02 11:47 宏风险HIGH持续——系统无故障,已知市场事件延续
**发现了什么:** 自愈执行器报盘中自检→宏观风险HIGH。核实后发现该风险已在11:27向Dad推送过完整报告,且到损位均未触发。这不是系统故障,是已知市场状态(全球半导体抛售)的延续。
**附带的data issue** portfolio.json的`currency`字段将所有港股(8只)标为CNY而非HKD。影响跨币种计算准确性。
- 根因追踪:`import_holding_xls.py`(line67)正确设HKD,但`strategy_lifecycle.py`(line2027)的`setdefault('currency','CNY')`在策略更新时覆盖了币种标记
- 修复计划:盘后(非交易时段)统一排查并修正currency字段在数据管道中的传播路径
**萃取知识:**
1. 自愈执行器对宏风险的报警是设计行为(health check标记risk=high→写TODO→升级处理),需要按"已知市场状态"处理而非"系统故障"
2. 腾讯(00700)距止损2.76%是所有持仓中最接近止损位的——本轮冲击前未被重点标记,暴露了"只关注风险最大的几个"忽略了中游风险
|
+41
View File
@@ -27,3 +27,44 @@
1. 韩国芯片巨头利税分配传闻是典型的「情绪性杀跌」——传闻已被辟谣,辟谣后指数快速回升。对A股科创板的影响主要通过半导体板块联动传导。 1. 韩国芯片巨头利税分配传闻是典型的「情绪性杀跌」——传闻已被辟谣,辟谣后指数快速回升。对A股科创板的影响主要通过半导体板块联动传导。
2. 科创50跌3%触发的HIGH信号本身是正确的——但需要结合消息面做上下文修正。这正是实时信号采集器(红绿灯)产生信号后需要LLM深度分析验证的原因。本次红绿灯正确捕捉到信号,LLM分析修正了级别。 2. 科创50跌3%触发的HIGH信号本身是正确的——但需要结合消息面做上下文修正。这正是实时信号采集器(红绿灯)产生信号后需要LLM深度分析验证的原因。本次红绿灯正确捕捉到信号,LLM分析修正了级别。
3. 重仓科技股在情绪杀跌日不做止损调整——这是系统性应对规则的正确应用。长芯博创距止损仅2.9%也不应在恐慌日调宽,等1-2个交易日确认趋势。 3. 重仓科技股在情绪杀跌日不做止损调整——这是系统性应对规则的正确应用。长芯博创距止损仅2.9%也不应在恐慌日调宽,等1-2个交易日确认趋势。
## 2026-07-02 全球半导体冲击:韩国熔断+美股半导体暴跌4.4%
**事件:** 自愈执行器上报盘中宏观风险HIGH信号(韩国KOSPI-6%触发熔断+费城半导体-4.4%+日经-2%)
**原因分析:**
- Meta拟出租过剩算力(布局AI云业务)→ 市场解读为AI资本开支见顶 → 全球半导体板块抛售
- 费城半导体指数跌4.4%NVDA-3.2%/AMD-4.3%/ASML-4.1%/MRVL-7.7%
- 韩国KOSPI跌6%触发熔断(三星-7%/SK海力士-8%+ 日经225跌2%
- 微软6月跌20%/8个月市值蒸发1.3万亿
- **注意:这不是传闻,Meta已确认动向** — 与7月1日韩国芯片传闻有本质区别
**市场状态(09:30开盘):**
- 上证指数 -1.42%(有韧性,非全面崩溃)
- 科创50 -4.33%(半导体重仓指数暴跌)
- 创业板指 -2.94%
- 深证成指 -2.41%
**持仓影响(A股开盘):**
- 中际旭创(15.27%) 1160 -5.16% 距止损8%
- 中芯国际A(5.44%) 146.5 -5.17% 距止损7%
- 博创科技(3.2%) 241.3 -4.99% 距止损9%
- 法拉电子(2.3%) 172.6 -5.48% 距止损4%
- 海博思创(6.31%) 255 -3.0% 距止损8%
- 华恒生物(5.25%) 16.0 -2.26%
- 防御股验证:紫金矿业+2% 黄金ETF+1.86% 模塑科技+2.87%
**定性:** 全球半导体/AI叙事冲击(板块冲击B类,但严重程度接近系统性)
- 区别昨天:昨天是韩国传闻辟谣后快速修复,今天是真实事件(Meta确认)+ 韩国熔断
- A股上证仅-1.42%说明不是全面系统性下跌,资金在板块间轮动(半导体→黄金/资源)
**操作:**
- 已推送给Dad XMPP报告
- 高景气被动杀跌持仓不动止损
- 防御股保留
- 等待HK开市检查港股持仓
**知识萃取:**
1. **传闻 vs 真实事件的应对区别:** 7月1日是传闻(韩国芯片利润传闻,辟谣后快速修复),7月2日是真实事件(Meta确认出租算力+韩国熔断)。传闻日可预期修复,真实事件需3-5日观察趋势确认。两者触发相同的「不动止损」规则,但后续跟踪周期不同。
2. **韩国熔断的历史信号意义:** 韩国KOSPI触发熔断是极罕见事件(上一次在2020年3月新冠初期),熔断本身不代表长期趋势转折——2020年熔断后KOSPI在半年内涨超80%。熔断是流动性冲击的信号,不是基本面崩塌。
3. **科创板-4.33%开盘但上证仅-1.42%的结构性分化验证了三维分析框架的价值:** 不看单一指数结论。科创50暴跌但上证不崩、黄金上涨、宁德时代翻红——说明是科技板块轮动式下跌而非全面系统性风险。仅看科创50会误判为系统性。
+782 -63946
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+9775 -9495
View File
File diff suppressed because it is too large Load Diff
+104 -580
View File
@@ -5,712 +5,236 @@
"name": "中际旭创", "name": "中际旭创",
"shares": 100, "shares": 100,
"cost": 1316.53, "cost": 1316.53,
"price": 1135.18,
"market_value": 113604.0,
"change_pct": -7.19,
"currency": "CNY",
"position_pct": 15.27, "position_pct": 15.27,
"is_active": 1, "_currency": "CNY"
"stop_loss": 1169.0,
"take_profit": 1339.19,
"entry_low": 1182.26,
"entry_high": 1248.91,
"action": null,
"strategy_updated": null,
"analysis": {
"stop_loss": 1169.0,
"take_profit": 1339.19,
"entry_low": 1182.26,
"entry_high": 1248.91,
"action": "持有观察 | ⚠️盈亏比偏低(1:1.4),不建议加仓 | 止损1169.0 | 目标1339.19 | 买入区1182.26~1248.91 | 信号:持有",
"tech_snapshot": "形态:带上影阴线/bearish 量价:主动买盘占优 强撑:1102.83 弱撑:1182.26 弱压:1289.83 强压:1394.99 | MA5=1262.5 MA10=1296.1 MA20=1247.2 MA60=1024.3",
"multi_tf_context": "多周期看多 | MA20=1247.2 | MA60=1024.3 | 长撑:日弱支撑=1122.0 | 长压:日强阻=1416.88",
"reassessed_at": "2026-07-01 15:01",
"status": "updated",
"rr_ratio": 1.43,
"action_note": "⚠️盈亏比偏低(1:1.4),不建议加仓",
"timing_signal": "持有"
},
"trigger": {
"stop_loss": 1169.0,
"entry_zone": "1182.26~1248.91",
"take_profit_zone": "0~1339.19"
},
"price": 1223.17,
"change_pct": -3.69
}, },
{ {
"code": "06869", "code": "06869",
"name": "长飞光纤光缆", "name": "长飞光纤光缆",
"shares": 500, "shares": 500,
"cost": 263.72, "cost": 263.72,
"price": 178.6,
"market_value": 89300.0,
"change_pct": -19.342,
"currency": "CNY",
"position_pct": 13.47, "position_pct": 13.47,
"is_active": 1, "_currency": "CNY"
"stop_loss": 205.71,
"take_profit": 300.74,
"entry_low": 239.4,
"entry_high": 251.37,
"action": null,
"strategy_updated": null,
"analysis": {
"stop_loss": 205.71,
"take_profit": 300.74,
"entry_low": 239.4,
"entry_high": 251.37,
"action": "持有观察 | ⚠️盈亏比偏低(1:0.9),不建议加仓 | 止损205.71 | 目标300.74 | 买入区239.4~251.37 | 信号:持有",
"tech_snapshot": "形态:锤子线/T字线/bullish 量价:数据不足 强撑:194.07 弱撑:239.4 弱压:261.73 强压:313.27 | MA5=258.84 MA10=252.78 MA20=246.28 MA60=231.33",
"multi_tf_context": "多周期看多 | MA20=246.28 | MA60=231.33 | 长撑:MA20=246.28 | 长压:日强阻=305.0",
"reassessed_at": "2026-07-01 15:01",
"status": "updated",
"rr_ratio": 0.94,
"action_note": "⚠️盈亏比偏低(1:0.9),不建议加仓",
"timing_signal": "持有"
},
"trigger": {
"stop_loss": 205.71,
"entry_zone": "239.4~251.37",
"take_profit_zone": "0~300.74"
},
"price": 221.69,
"change_pct": 6.68
}, },
{ {
"code": "01478", "code": "01478",
"name": "丘钛科技", "name": "丘钛科技",
"shares": 11000, "shares": 11000,
"cost": 13.47, "cost": 13.47,
"price": 5.99,
"market_value": 65890.0,
"change_pct": 0.729,
"currency": "CNY",
"position_pct": 7.97, "position_pct": 7.97,
"is_active": 1, "_currency": "CNY"
"stop_loss": 6.18,
"take_profit": 7.2,
"entry_low": 6.17,
"entry_high": 7.2,
"action": "深套持有 | 深套持有 | 止损7.33 | 目标10.39 | 买入区7.88~9.19 | 信号:持有",
"strategy_updated": "2026-06-19 16:01",
"analysis": {
"stop_loss": 6.18,
"take_profit": 7.2,
"entry_low": 6.17,
"entry_high": 7.2,
"action": "深套持有 | 深套持有 | 止损6.18 | 目标7.2 | 买入区6.17~7.2 | 信号:持有",
"tech_snapshot": "形态:光头光脚阴线/neutral 量价:数据不足 强撑:6.36 弱撑:6.69 弱压:7.09 强压:7.5 | MA5=8.98 MA10=9.17 MA20=9.44 MA60=8.88",
"multi_tf_context": "震荡/无明显方向 | MA20=9.44 | MA60=8.88 | 长撑:日强支撑=6.6 | 长压:日强阻=10.5",
"reassessed_at": "2026-07-01 15:01",
"status": "updated",
"rr_ratio": 0.62,
"action_note": "深套持有",
"timing_signal": "持有"
},
"trigger": {
"stop_loss": 6.18,
"entry_zone": "6.17~7.2",
"take_profit_zone": "0~7.2"
},
"price": 5.95,
"change_pct": -0.58
}, },
{ {
"code": "601899", "code": "601899",
"name": "紫金矿业", "name": "紫金矿业",
"shares": 2400, "shares": 2400,
"cost": 39.89, "cost": 39.89,
"price": 26.35,
"market_value": 63048.0,
"change_pct": 4.94,
"currency": "CNY",
"position_pct": 7.34, "position_pct": 7.34,
"is_active": 1, "_currency": "CNY"
"stop_loss": 23.07,
"take_profit": 25.51,
"entry_low": 22.6,
"entry_high": 26.37,
"action": "深套持有 | 深套持有 | 止损24.48 | 目标34.47 | 买入区26.72~31.17 | 信号:持有",
"strategy_updated": "2026-06-19 16:01",
"analysis": {
"stop_loss": 23.07,
"take_profit": 25.51,
"entry_low": 22.6,
"entry_high": 26.37,
"action": "深套持有 | 深套持有 | 止损23.07 | 目标25.51 | 买入区22.6~26.37 | 信号:持有",
"tech_snapshot": "形态:小阳线/neutral 量价:主动买盘占优 强撑:23.49 弱撑:24.5 弱压:25.63 强压:26.57 | MA5=33.51 MA10=35.08 MA20=36.34 MA60=36.5",
"multi_tf_context": "震荡/无明显方向 | MA20=36.34 | MA60=36.5 | 长撑:日弱支撑=24.7 | 长压:周强阻=35.62",
"reassessed_at": "2026-07-01 15:02",
"status": "updated",
"rr_ratio": 0.39,
"action_note": "深套持有",
"timing_signal": "持有"
},
"trigger": {
"stop_loss": 23.07,
"entry_zone": "22.6~26.37",
"take_profit_zone": "0~25.51"
},
"price": 25.11,
"change_pct": -0.12
}, },
{ {
"code": "688411", "code": "688411",
"name": "海博思创", "name": "海博思创",
"shares": 200, "shares": 200,
"cost": 266.95, "cost": 266.95,
"price": 258.3,
"market_value": 51776.0,
"change_pct": -1.75,
"currency": "CNY",
"position_pct": 6.31, "position_pct": 6.31,
"is_active": 1, "_currency": "CNY"
"stop_loss": 246.94,
"take_profit": 309.13,
"entry_low": 244.27,
"entry_high": 256.48,
"action": "盈利良好 | 止损253.82 | 目标316.5 | 买入区273.21~286.87 | 信号:持有",
"strategy_updated": "2026-06-19 16:01",
"analysis": {
"stop_loss": 246.94,
"take_profit": 309.13,
"entry_low": 244.27,
"entry_high": 256.48,
"action": "持有观察 | 止损246.94 | 目标309.13 | 买入区244.27~256.48 | 信号:持有",
"tech_snapshot": "形态:带下影阴线/neutral 量价:买卖均衡 强撑:232.96 弱撑:244.27 弱压:291.2 强压:322.01 | MA5=256.08 MA10=249.18 MA20=246.95 MA60=242.64",
"multi_tf_context": "震荡/无明显方向 | MA20=246.95 | MA60=242.64 | 长撑:MA20=246.95 | 长压:周强阻=307.58",
"reassessed_at": "2026-07-01 15:02",
"status": "updated",
"rr_ratio": 1.98,
"action_note": "",
"timing_signal": "持有"
},
"trigger": {
"stop_loss": 246.94,
"entry_zone": "244.27~256.48",
"take_profit_zone": "0~309.13"
},
"price": 262.89,
"change_pct": -9.72
}, },
{ {
"code": "688981", "code": "688981",
"name": "中芯国际", "name": "中芯国际",
"shares": 300, "shares": 300,
"cost": 126.07, "cost": 126.07,
"price": 146.32,
"market_value": 44112.0,
"change_pct": -5.28,
"currency": "CNY",
"position_pct": 5.44, "position_pct": 5.44,
"is_active": 1, "_currency": "CNY"
"stop_loss": 149.85,
"take_profit": 176.42,
"entry_low": 148.9,
"entry_high": 156.34,
"action": "盈利良好 | 止损132.76 | 目标164.45 | 买入区134.18~140.89 | 信号:持有",
"strategy_updated": "2026-06-19 16:01",
"analysis": {
"stop_loss": 149.85,
"take_profit": 176.42,
"entry_low": 148.9,
"entry_high": 156.34,
"action": "盈利良好 | 止损149.85 | 目标176.42 | 买入区148.9~156.34 | 信号:持有",
"tech_snapshot": "形态:带上影阴线/bearish 量价:买卖均衡 强撑:132.01 弱撑:148.9 弱压:163.47 强压:183.77 | MA5=154.35 MA10=148.6 MA20=138.49 MA60=124.68",
"multi_tf_context": "震荡/无明显方向 | MA20=138.49 | MA60=124.68 | 长撑:MA20=138.49 | 长压:日强阻=166.88",
"reassessed_at": "2026-07-01 15:02",
"status": "updated",
"rr_ratio": 5.25,
"action_note": "",
"timing_signal": "持有"
},
"trigger": {
"stop_loss": 149.85,
"entry_zone": "148.9~156.34",
"take_profit_zone": "0~176.42"
},
"price": 154.48,
"change_pct": -2.73
}, },
{ {
"code": "01888", "code": "01888",
"name": "建滔积层板", "name": "建滔积层板",
"shares": 500, "shares": 500,
"cost": 88.23, "cost": 88.23,
"price": 72.83,
"market_value": 36415.0,
"change_pct": -15.28,
"currency": "CNY",
"position_pct": 5.28, "position_pct": 5.28,
"is_active": 1, "_currency": "CNY"
"stop_loss": 92.33,
"take_profit": 103.21,
"entry_low": 94.93,
"entry_high": 99.68,
"action": "盈利持有 | 短炒强趋势持 | 止损86.34 | 目标141.9 | 买入区85.82~90.11 | 信号:强趋势持",
"strategy_updated": "2026-06-19 16:01",
"analysis": {
"stop_loss": 92.33,
"take_profit": 103.21,
"entry_low": 94.93,
"entry_high": 99.68,
"action": "盈利良好 | 止损92.33 | 目标103.21 | 买入区94.93~99.68 | 信号:持有",
"tech_snapshot": "形态:带上影阳线/neutral 量价:数据不足 强撑:84.27 弱撑:94.93 弱压:102.93 强压:113.17 | MA5=98.35 MA10=93.72 MA20=76.92 MA60=50.12",
"multi_tf_context": "多周期看多 | MA20=76.92 | MA60=50.12 | 长撑:MA20=76.92 | 长压:日强阻=107.2",
"reassessed_at": "2026-07-01 15:01",
"status": "updated",
"rr_ratio": 3.32,
"action_note": "",
"timing_signal": "持有"
},
"trigger": {
"stop_loss": 92.33,
"entry_zone": "94.93~99.68",
"take_profit_zone": "0~103.21"
},
"price": 86.06,
"change_pct": 2.96
}, },
{ {
"code": "688639", "code": "688639",
"name": "华恒生物", "name": "华恒生物",
"shares": 2800, "shares": 2800,
"cost": 21.51, "cost": 21.51,
"price": 17.18,
"market_value": 48244.0,
"change_pct": 4.95,
"currency": "CNY",
"position_pct": 5.25, "position_pct": 5.25,
"is_active": 1, "_currency": "CNY"
"stop_loss": 14.96,
"take_profit": 18.7,
"entry_low": 14.73,
"entry_high": 17.19,
"action": null,
"strategy_updated": null,
"analysis": {
"stop_loss": 14.96,
"take_profit": 18.7,
"entry_low": 14.73,
"entry_high": 17.19,
"action": "深套持有 | 深套持有 | 止损14.96 | 目标18.7 | 买入区14.73~17.19 | 信号:持有",
"tech_snapshot": "形态:锤子线/T字线/bullish 量价:主动买盘占优 强撑:13.44 弱撑:15.86 弱压:16.69 强压:18.92 | MA5=32.72 MA10=34.17 MA20=36.22 MA60=34.41",
"multi_tf_context": "多周期看多 | MA20=36.22 | MA60=34.41 | 长撑:日弱支撑=15.65 | 长压:日强阻=22.62",
"reassessed_at": "2026-07-01 15:02",
"status": "updated",
"rr_ratio": 0.87,
"action_note": "深套持有",
"timing_signal": "持有"
},
"trigger": {
"stop_loss": 14.96,
"entry_zone": "14.73~17.19",
"take_profit_zone": "0~18.7"
},
"price": 16.37,
"change_pct": 1.43
}, },
{ {
"code": "300750", "code": "300750",
"name": "宁德时代", "name": "宁德时代",
"shares": 100, "shares": 100,
"cost": 401.78, "cost": 401.78,
"price": 386.3,
"market_value": 38495.0,
"change_pct": 0.64,
"currency": "CNY",
"position_pct": 4.64, "position_pct": 4.64,
"is_active": 1, "_currency": "CNY"
"stop_loss": 362.31,
"take_profit": 404.56,
"entry_low": 372.23,
"entry_high": 381.61,
"action": "持有观察 | 止损345.04 | 目标414.6 | 买入区384.35~397.12 | 信号:弱势持有",
"strategy_updated": "2026-06-19 16:01",
"analysis": {
"stop_loss": 362.31,
"take_profit": 404.56,
"entry_low": 372.23,
"entry_high": 381.61,
"action": "持有观察 | ⚠️盈亏比偏低(1:0.9),不建议加仓 | 止损362.31 | 目标404.56 | 买入区372.23~381.61 | 信号:持有",
"tech_snapshot": "形态:锤子线/T字线/bullish 量价:买卖均衡 强撑:341.8 弱撑:372.23 弱压:393.23 强压:421.42 | MA5=390.94 MA10=394.21 MA20=396.97 MA60=414.12",
"multi_tf_context": "震荡/无明显方向 | MA20=396.97 | MA60=414.12 | 长撑:日弱支撑=378.2 | 长压:周强阻=468.75",
"reassessed_at": "2026-07-01 15:02",
"status": "updated",
"rr_ratio": 0.89,
"action_note": "⚠️盈亏比偏低(1:0.9),不建议加仓",
"timing_signal": "持有"
},
"trigger": {
"stop_loss": 362.31,
"entry_zone": "372.23~381.61",
"take_profit_zone": "0~404.56"
},
"price": 383.84,
"change_pct": -2.33
}, },
{ {
"code": "01211", "code": "01211",
"name": "比亚迪股份", "name": "比亚迪股份",
"shares": 600, "shares": 600,
"cost": 104.87, "cost": 104.87,
"price": 68.41,
"market_value": 41070.0,
"change_pct": 8.903,
"currency": "CNY",
"position_pct": 4.62, "position_pct": 4.62,
"is_active": 1, "_currency": "CNY"
"stop_loss": 66.58,
"take_profit": 73.73,
"entry_low": 65.2,
"entry_high": 76.07,
"action": "深套持有 | 深套持有 | 止损63.99 | 目标87.07 | 买入区72.77~84.89 | 信号:持有",
"strategy_updated": "2026-06-19 16:01",
"analysis": {
"stop_loss": 66.58,
"take_profit": 73.73,
"entry_low": 65.2,
"entry_high": 76.07,
"action": "深套持有 | 深套持有 | 止损66.58 | 目标73.73 | 买入区65.2~76.07 | 信号:持有",
"tech_snapshot": "形态:十字星/neutral 量价:数据不足 强撑:68.5 弱撑:71.2 弱压:73.9 强压:76.8 | MA5=96.88 MA10=96.41 MA20=97.91 MA60=98.22",
"multi_tf_context": "多周期看多 | MA20=97.91 | MA60=98.22 | 长撑:日弱支撑=72.2 | 长压:日强阻=97.15",
"reassessed_at": "2026-07-01 15:01",
"status": "updated",
"rr_ratio": 0.4,
"action_note": "深套持有",
"timing_signal": "持有"
},
"trigger": {
"stop_loss": 66.58,
"entry_zone": "65.2~76.07",
"take_profit_zone": "0~73.73"
},
"price": 62.89,
"change_pct": -0.62
}, },
{ {
"code": "02202", "code": "02202",
"name": "万科企业", "name": "万科企业",
"shares": 19700, "shares": 19700,
"cost": 4.67, "cost": 4.67,
"price": 1.92,
"market_value": 38021.0,
"change_pct": 4.717,
"currency": "CNY",
"position_pct": 4.6, "position_pct": 4.6,
"is_active": 1, "_currency": "CNY"
"stop_loss": 1.95,
"take_profit": 2.31,
"entry_low": 1.91,
"entry_high": 2.23,
"action": "深套持有 | 深套持有 | 止损2.0 | 目标2.85 | 买入区2.18~2.54 | 信号:持有",
"strategy_updated": "2026-06-19 16:01",
"analysis": {
"stop_loss": 1.95,
"take_profit": 2.31,
"entry_low": 1.91,
"entry_high": 2.23,
"action": "深套持有 | 深套持有 | 止损1.95 | 目标2.31 | 买入区1.91~2.23 | 信号:持有",
"tech_snapshot": "形态:光头光脚阴线/bearish 量价:数据不足 强撑:1.89 弱撑:2.07 弱压:2.21 强压:2.41 | MA5=3.37 MA10=3.39 MA20=3.5 MA60=3.52",
"multi_tf_context": "多周期看多 | MA20=3.5 | MA60=3.52 | 长撑:日强支撑=2.1 | 长压:日强阻=2.85",
"reassessed_at": "2026-07-01 15:01",
"status": "updated",
"rr_ratio": 0.91,
"action_note": "深套持有",
"timing_signal": "持有"
},
"trigger": {
"stop_loss": 1.95,
"entry_zone": "1.91~2.23",
"take_profit_zone": "0~2.31"
},
"price": 1.84,
"change_pct": -4.07
}, },
{ {
"code": "00700", "code": "00700",
"name": "腾讯", "name": "腾讯",
"shares": 100, "shares": 100,
"cost": null, "cost": null,
"price": 378.36,
"market_value": 37784.0,
"change_pct": 1.536,
"currency": "CNY",
"position_pct": null, "position_pct": null,
"is_active": 1, "_currency": "CNY"
"stop_loss": 416.91,
"take_profit": 434.43,
"entry_low": 421.2,
"entry_high": 429.72,
"action": "持有观察 | ⚠️盈亏比偏低(1:1.0),不建议加仓 | 止损387.49 | 目标496.33 | 买入区435.13~440.67 | 信号:持有",
"strategy_updated": "2026-06-19 16:01",
"analysis": {
"stop_loss": 416.91,
"take_profit": 434.43,
"entry_low": 421.2,
"entry_high": 429.72,
"action": "盈利持有 | ⚠️盈亏比不足1:1.5,不建议买入 | 损414.51 | 盈452.53 | 买421.2~429.72",
"tech_snapshot": "形态:带上影阳线/neutral 量价:数据不足 强撑:403.33 弱撑:420.2 弱压:437.47 强压:452.53 | MA5=620.7 MA10=621.4 MA20=614.35 MA60=561.43",
"multi_tf_context": "多周期看多 | MA20=614.35 | MA60=561.43 | 长撑:日弱支撑=412.6 | 长压:周强阻=526.5",
"reassessed_at": "2026-07-01 15:01",
"status": "review",
"rr_ratio": 1.49,
"action_note": "⚠️盈亏比不足1:1.5,不建议买入",
"timing_signal": "信号不充分"
},
"trigger": {
"stop_loss": 416.91,
"entry_zone": "421.2~429.72",
"take_profit_zone": "0~434.43"
},
"price": 373.07,
"change_pct": 2.28
}, },
{ {
"code": "00981", "code": "00981",
"name": "中芯国际", "name": "中芯国际",
"shares": 500, "shares": 500,
"cost": 75.94, "cost": 75.94,
"price": 69.88,
"market_value": 34635.0,
"change_pct": -9.843,
"currency": "CNY",
"position_pct": 4.2, "position_pct": 4.2,
"is_active": 1, "_currency": "CNY"
"stop_loss": 86.72,
"take_profit": 96.86,
"entry_low": 84.8,
"entry_high": 89.04,
"action": "盈利持有 | ⚠️盈亏比偏低(1:1.0),不建议加仓 | 止损67.69 | 目标87.26 | 买入区73.68~76.57 | 信号:持有",
"strategy_updated": "2026-06-19 16:01",
"analysis": {
"stop_loss": 86.72,
"take_profit": 96.86,
"entry_low": 84.8,
"entry_high": 89.04,
"action": "盈利良好 | 止损86.72 | 目标96.86 | 买入区84.8~89.04 | 信号:持有",
"tech_snapshot": "形态:光头光脚阳线/bullish 量价:数据不足 强撑:75.9 弱撑:84.8 弱压:92.55 强压:100.9 | MA5=85.0 MA10=80.8 MA20=78.58 MA60=71.43",
"multi_tf_context": "震荡/无明显方向 | MA20=78.58 | MA60=71.43 | 长撑:MA20=78.58 | 长压:周强阻=93.0",
"reassessed_at": "2026-07-01 15:01",
"status": "updated",
"rr_ratio": 2.57,
"action_note": "",
"timing_signal": "持有"
},
"trigger": {
"stop_loss": 86.72,
"entry_zone": "84.8~89.04",
"take_profit_zone": "0~96.86"
},
"price": 77.6,
"change_pct": 5.42
}, },
{ {
"code": "300548", "code": "300548",
"name": "长芯博创", "name": "长芯博创",
"shares": 100, "shares": 100,
"cost": 231.46, "cost": 231.46,
"price": 225.0,
"market_value": 22592.0,
"change_pct": -11.42,
"currency": "CNY",
"position_pct": 3.2, "position_pct": 3.2,
"is_active": 1, "_currency": "CNY"
"stop_loss": 246.38,
"take_profit": 291.58,
"entry_low": 241.67,
"entry_high": 253.75,
"action": "盈利良好 | 短炒强趋势持 | 止损251.24 | 目标413.9 | 买入区269.8~283.29 | 信号:强趋势持",
"strategy_updated": "2026-06-19 16:01",
"analysis": {
"stop_loss": 246.38,
"take_profit": 291.58,
"entry_low": 241.67,
"entry_high": 253.75,
"action": "盈利良好 | 止损246.38 | 目标291.58 | 买入区241.67~253.75 | 信号:持有",
"tech_snapshot": "形态:光头光脚阴线/bearish 量价:主动买盘占优 强撑:222.4 弱撑:241.67 弱压:278.0 强压:303.73 | MA5=266.91 MA10=275.27 MA20=256.44 MA60=247.14",
"multi_tf_context": "多周期看多 | MA20=256.44 | MA60=247.14 | 长撑:MA60=247.14 | 长压:日强阻=309.98",
"reassessed_at": "2026-07-01 15:02",
"status": "updated",
"rr_ratio": 4.03,
"action_note": "",
"timing_signal": "持有"
},
"trigger": {
"stop_loss": 246.38,
"entry_zone": "241.67~253.75",
"take_profit_zone": "0~291.58"
},
"price": 254.0,
"change_pct": -8.63
}, },
{ {
"code": "518880", "code": "518880",
"name": "黄金ETF华安", "name": "黄金ETF华安",
"shares": 2400, "shares": 2400,
"cost": 12.19, "cost": 12.19,
"price": 8.45,
"market_value": 20280.0,
"change_pct": 2.13,
"currency": "CNY",
"position_pct": 2.45, "position_pct": 2.45,
"is_active": 1, "_currency": "CNY"
"stop_loss": 7.45,
"take_profit": 8.58,
"entry_low": 7.44,
"entry_high": 8.68,
"action": "深套持有 | 深套持有 | 止损7.05 | 目标9.17 | 买入区8.02~9.35 | 信号:持有",
"strategy_updated": "2026-06-19 16:01",
"analysis": {
"stop_loss": 7.45,
"take_profit": 8.58,
"entry_low": 7.44,
"entry_high": 8.68,
"action": "深套持有 | 深套持有 | 止损7.45 | 目标8.58 | 买入区7.44~8.68 | 信号:持有",
"tech_snapshot": "形态:小阴线/bearish 量价:数据不足 强撑:7.61 弱撑:8.25 弱压:8.38 强压:8.94 | MA5=9.47 MA10=9.53 MA20=9.86 MA60=10.33",
"multi_tf_context": "震荡/无明显方向 | MA20=9.86 | MA60=10.33 | 长撑:日弱支撑=8.26 | 长压:周强阻=10.15",
"reassessed_at": "2026-07-01 15:02",
"status": "updated",
"rr_ratio": 0.54,
"action_note": "深套持有",
"timing_signal": "持有"
},
"trigger": {
"stop_loss": 7.45,
"entry_zone": "7.44~8.68",
"take_profit_zone": "0~8.58"
},
"price": 8.27,
"change_pct": -1.28
}, },
{ {
"code": "300035", "code": "300035",
"name": "中科电气", "name": "中科电气",
"shares": 1400, "shares": 1400,
"cost": 22.29, "cost": 22.29,
"price": 14.33,
"market_value": 20062.0,
"change_pct": -0.76,
"currency": "CNY",
"position_pct": 2.42, "position_pct": 2.42,
"is_active": 1, "_currency": "CNY"
"stop_loss": 13.01,
"take_profit": 15.14,
"entry_low": 13.0,
"entry_high": 15.16,
"action": "深套持有 | 深套持有 | 止损13.74 | 目标19.0 | 买入区15.63~18.24 | 信号:持有",
"strategy_updated": "2026-06-19 16:01",
"analysis": {
"stop_loss": 13.01,
"take_profit": 15.14,
"entry_low": 13.0,
"entry_high": 15.16,
"action": "深套持有 | 深套持有 | 止损13.01 | 目标15.14 | 买入区13.0~15.16 | 信号:持有",
"tech_snapshot": "形态:锤子线/T字线/bullish 量价:主动卖盘占优 强撑:13.01 弱撑:14.12 弱压:14.71 强压:15.77 | MA5=21.52 MA10=21.86 MA20=22.15 MA60=21.45",
"multi_tf_context": "震荡/无明显方向 | MA20=22.15 | MA60=21.45 | 长撑:日弱支撑=14.07 | 长压:日强阻=18.23",
"reassessed_at": "2026-07-01 15:01",
"status": "updated",
"rr_ratio": 0.61,
"action_note": "深套持有",
"timing_signal": "持有"
},
"trigger": {
"stop_loss": 13.01,
"entry_zone": "13.0~15.16",
"take_profit_zone": "0~15.14"
},
"price": 14.44,
"change_pct": 0.14
}, },
{ {
"code": "000700", "code": "000700",
"name": "模塑科技", "name": "模塑科技",
"shares": 1400, "shares": 1400,
"cost": 14.83, "cost": 14.83,
"price": 16.87,
"market_value": 23618.0,
"change_pct": 9.97,
"currency": "CNY",
"position_pct": 2.41, "position_pct": 2.41,
"is_active": 1, "_currency": "CNY"
"stop_loss": 13.91,
"take_profit": 15.54,
"entry_low": 13.32,
"entry_high": 14.09,
"action": null,
"strategy_updated": null,
"analysis": {
"stop_loss": 13.91,
"take_profit": 15.54,
"entry_low": 13.32,
"entry_high": 14.09,
"action": "盈利持有 | ⚠️盈亏比极低,关注 | 止损13.91 | 目标15.54 | 买入区13.32~14.09 | 信号:持有",
"tech_snapshot": "形态:带上影阳线/neutral 量价:主动买盘占优 强撑:13.28 弱撑:14.55 弱压:16.1 强压:16.24 | MA5=14.44 MA10=14.83 MA20=15.44 MA60=13.73",
"multi_tf_context": "多周期看多 | MA20=15.44 | MA60=13.73 | 长撑:日弱支撑=13.78 | 长压:日强阻=18.66",
"reassessed_at": "2026-07-01 15:00",
"status": "manual",
"rr_ratio": 0.14,
"action_note": "⚠️盈亏比极低,关注",
"timing_signal": "持有"
},
"trigger": {
"stop_loss": 13.91,
"entry_zone": "13.32~14.09",
"take_profit_zone": "0~15.54"
},
"price": 15.34,
"change_pct": 3.93
}, },
{ {
"code": "600563", "code": "600563",
"name": "法拉电子", "name": "法拉电子",
"shares": 100, "shares": 100,
"cost": 147.18, "cost": 147.18,
"price": 164.32,
"market_value": 16460.0,
"change_pct": -9.99,
"currency": "CNY",
"position_pct": 2.3, "position_pct": 2.3,
"is_active": 1, "_currency": "CNY"
"stop_loss": 169.99,
"take_profit": 188.19,
"entry_low": 175.29,
"entry_high": 184.05,
"action": "盈利良好 | 止损161.41 | 目标192.67 | 买入区165.51~173.79 | 信号:持有",
"strategy_updated": "2026-06-19 16:01",
"analysis": {
"stop_loss": 169.99,
"take_profit": 188.19,
"entry_low": 175.29,
"entry_high": 184.05,
"action": "盈利良好 | 止损169.99 | 目标188.19 | 买入区175.29~184.05 | 信号:持有",
"tech_snapshot": "形态:光头光脚阴线/bearish 量价:买卖均衡 强撑:171.72 弱撑:175.29 弱压:192.5 强压:206.35 | MA5=187.94 MA10=179.22 MA20=168.75 MA60=144.49",
"multi_tf_context": "多周期看多 | MA20=168.75 | MA60=144.49 | 长撑:MA20=168.75 | 长压:日强阻=198.8",
"reassessed_at": "2026-07-01 15:02",
"status": "updated",
"rr_ratio": 3.28,
"action_note": "",
"timing_signal": "持有"
},
"trigger": {
"stop_loss": 169.99,
"entry_zone": "175.29~184.05",
"take_profit_zone": "0~188.19"
},
"price": 182.55,
"change_pct": -4.32
}, },
{ {
"code": "01088", "code": "01088",
"name": "中国神华", "name": "中国神华",
"shares": 500, "shares": 500,
"cost": 45.89, "cost": 45.89,
"position_pct": 2.14, "price": 34.26,
"is_active": 1, "market_value": 17115.0,
"stop_loss": 38.92, "change_pct": 1.503,
"take_profit": 41.97,
"entry_low": 39.41,
"entry_high": 40.45,
"action": "持有观察 | ⚠️盈亏比偏低(1:1.3),不建议加仓 | 止损35.09 | 目标42.9 | 买入区41.66~42.8 | 信号:持有",
"strategy_updated": "2026-06-19 16:01",
"analysis": {
"stop_loss": 38.92,
"take_profit": 41.97,
"entry_low": 39.41,
"entry_high": 40.45,
"action": "持有观察 | ⚠️盈亏比偏低(1:1.4),不建议加仓 | 止损38.92 | 目标41.97 | 买入区39.41~40.45 | 信号:持有",
"tech_snapshot": "形态:光头光脚阴线/bearish 量价:数据不足 强撑:38.44 弱撑:39.41 弱压:41.15 强压:42.45 | MA5=40.86 MA10=41.76 MA20=43.74 MA60=45.14",
"multi_tf_context": "震荡/无明显方向 | MA20=43.74 | MA60=45.14 | 长撑:日弱支撑=40.0 | 长压:月强阻=49.62",
"reassessed_at": "2026-07-01 15:01",
"status": "updated",
"rr_ratio": 1.39,
"action_note": "⚠️盈亏比偏低(1:1.4),不建议加仓",
"timing_signal": "持有"
},
"trigger": {
"stop_loss": 38.92,
"entry_zone": "39.41~40.45",
"take_profit_zone": "0~41.97"
},
"price": 34.82,
"change_pct": -2.38
}
],
"cash": 92678.85,
"total_market_value": 835552.6,
"total_assets": 989902.25,
"total_pl": 0,
"position_pct": 86.65,
"updated_at": "2026-07-01 16:58",
"source": "/home/hmo/stocks/holding.xls",
"frozen_cash": 39481.4,
"available_cash": 92678.85,
"frozen": 39481.4,
"total_cash": 132160.25,
"cash_updated_at": "2026-06-29 12:34",
"recent_trades": [
{
"code": "600563",
"name": "法拉电子",
"action": "sell",
"price": 189.2,
"shares": 100,
"amount": 18920.0,
"timestamp": "2026-06-29 10:43"
}
],
"total_mv": 857742.0,
"note": "cash fixed from screenshot 6/29, prices=CNY",
"currency": "CNY", "currency": "CNY",
"last_verified_at": "2026-06-29 22:28", "position_pct": 2.14,
"_total_mv": 835552.6, "_currency": "CNY"
"_total_cash": 132160.25,
"_total_assets": 967712.85,
"cash_history": [
{
"time": "2026-06-29 22:23:47",
"cash": 92678.85,
"frozen": 39481.4,
"source": "manual:post-法拉电子-sell-100shares@189.2",
"formula": "初始可用73758.85+法拉电子18920"
},
{
"time": "2026-06-29 22:28",
"cash": 92678.85,
"frozen": 39481.4,
"total_mv": 835552.6,
"total_assets": 967712.85,
"source": "price_monitor_auto"
} }
] ],
"total_assets": 902797.0,
"total_mv": 822321.0,
"stock_value": null,
"cash": 80476.0,
"frozen_cash": 0.0,
"position_pct": 91.09,
"currency": "CNY",
"updated_at": "2026-07-02 13:46"
} }
File diff suppressed because it is too large Load Diff
+166 -1020
View File
File diff suppressed because it is too large Load Diff
+5
View File
@@ -21,6 +21,11 @@
"content": "长飞光纤光缆(06869) 255.40+6.68%放量大涨,持有等站上成本263.72;腾讯(00700) 429.80+2.28%,买入区435-440依然可加;中芯H(00981) 89.40+", "content": "长飞光纤光缆(06869) 255.40+6.68%放量大涨,持有等站上成本263.72;腾讯(00700) 429.80+2.28%,买入区435-440依然可加;中芯H(00981) 89.40+",
"report_id": "cron_99c06255590a_2026-07-01_08-39-42" "report_id": "cron_99c06255590a_2026-07-01_08-39-42"
}, },
{
"time": "2026-07-02T08:55:30.266659",
"content": "- **模塑科技(000700)** 15.54 / 止损13.91 — 昨日+5.28%强势,守住15持有",
"report_id": "cron_99c06255590a_2026-07-02_08-32-48"
},
{ {
"time": "2026-06-30T08:55:46.708460", "time": "2026-06-30T08:55:46.708460",
"content": "- 模塑科技000700 13.86 | 买入区13.33~14.09 **(仍在区内,但已破止损)**", "content": "- 模塑科技000700 13.86 | 买入区13.33~14.09 **(仍在区内,但已破止损)**",
+10
View File
@@ -131,6 +131,16 @@
"content": "长飞光纤光缆(06869) 255.40+6.68%放量大涨,持有等站上成本263.72;腾讯(00700) 429.80+2.28%,买入区435-440依然可加;中芯H(00981) 89.40+", "content": "长飞光纤光缆(06869) 255.40+6.68%放量大涨,持有等站上成本263.72;腾讯(00700) 429.80+2.28%,买入区435-440依然可加;中芯H(00981) 89.40+",
"report_id": "cron_99c06255590a_2026-07-01_08-39-42" "report_id": "cron_99c06255590a_2026-07-01_08-39-42"
}, },
{
"time": "2026-07-02T08:55:30.266659",
"content": "- **腾讯(00700)** 429.8 / 止损414.51 止盈452.53 — 入场区间421~430,持有待突破",
"report_id": "cron_99c06255590a_2026-07-02_08-32-48"
},
{
"time": "2026-07-02T08:55:30.266659",
"content": "- **模塑科技(000700)** 15.54 / 止损13.91 — 昨日+5.28%强势,守住15持有",
"report_id": "cron_99c06255590a_2026-07-02_08-32-48"
},
{ {
"time": "2026-06-02T11:55:44.093905", "time": "2026-06-02T11:55:44.093905",
"content": "❌ 反例:腾讯00700,底仓100股(3.59%),浮盈+4.79%。看到\"距止盈470仅0.77%\"就建议触及减仓清仓 —— 机械执行,未考虑底仓属性+浮盈幅度。", "content": "❌ 反例:腾讯00700,底仓100股(3.59%),浮盈+4.79%。看到\"距止盈470仅0.77%\"就建议触及减仓清仓 —— 机械执行,未考虑底仓属性+浮盈幅度。",
+5
View File
@@ -66,6 +66,11 @@
"content": "**丘钛科技(01478)** 现价6.86(-0.58%) | 仓位7.97% | 止损7.33", "content": "**丘钛科技(01478)** 现价6.86(-0.58%) | 仓位7.97% | 止损7.33",
"report_id": "cron_99c06255590a_2026-07-01_08-39-42" "report_id": "cron_99c06255590a_2026-07-01_08-39-42"
}, },
{
"time": "2026-07-02T08:55:30.266659",
"content": "**丘钛科技(01478)** — 现价6.86 | 成本13.47深度套牢-49%,止损6.18仅10%空间。手机链受韩国科技股崩盘情绪拖累,破6.5必须执行止损。",
"report_id": "cron_99c06255590a_2026-07-02_08-32-48"
},
{ {
"time": "2026-06-02T12:55:54.834592", "time": "2026-06-02T12:55:54.834592",
"content": "| 丘钛科技(01478) | 10.12 | -1.17% | 9.19% | 深套持有,止损9.0 |", "content": "| 丘钛科技(01478) | 10.12 | -1.17% | 9.19% | 深套持有,止损9.0 |",
+5
View File
@@ -21,6 +21,11 @@
"content": "长飞光纤光缆(06869) 255.40+6.68%放量大涨,持有等站上成本263.72;腾讯(00700) 429.80+2.28%,买入区435-440依然可加;中芯H(00981) 89.40+", "content": "长飞光纤光缆(06869) 255.40+6.68%放量大涨,持有等站上成本263.72;腾讯(00700) 429.80+2.28%,买入区435-440依然可加;中芯H(00981) 89.40+",
"report_id": "cron_99c06255590a_2026-07-01_08-39-42" "report_id": "cron_99c06255590a_2026-07-01_08-39-42"
}, },
{
"time": "2026-07-02T08:55:30.266659",
"content": "- **长飞光纤(06869)** 255.4 / 止损205.71 — 浮亏-3%,光通信受半导拖累,250不破则持",
"report_id": "cron_99c06255590a_2026-07-02_08-32-48"
},
{ {
"time": "2026-06-02T13:56:05.495125", "time": "2026-06-02T13:56:05.495125",
"content": "🔺**长飞光纤(06869)** | 231.00 +9.90% | 买入区210~220已超出,等回调再入3%", "content": "🔺**长飞光纤(06869)** | 231.00 +9.90% | 买入区210~220已超出,等回调再入3%",
+5
View File
@@ -61,6 +61,11 @@
"content": "长飞光纤光缆(06869) 255.40+6.68%放量大涨,持有等站上成本263.72;腾讯(00700) 429.80+2.28%,买入区435-440依然可加;中芯H(00981) 89.40+", "content": "长飞光纤光缆(06869) 255.40+6.68%放量大涨,持有等站上成本263.72;腾讯(00700) 429.80+2.28%,买入区435-440依然可加;中芯H(00981) 89.40+",
"report_id": "cron_99c06255590a_2026-07-01_08-39-42" "report_id": "cron_99c06255590a_2026-07-01_08-39-42"
}, },
{
"time": "2026-07-02T08:55:30.266659",
"content": "- **宁德时代(300750)** 386.45 / 止损362.31 — 买入区间371~381已触发,现价略高,挂单378加仓",
"report_id": "cron_99c06255590a_2026-07-02_08-32-48"
},
{ {
"time": "2026-06-02T12:55:54.834592", "time": "2026-06-02T12:55:54.834592",
"content": "| 宁德时代(300750) | 427.84 | +1.84% | 4.04% | 持有,止损400止盈460 |", "content": "| 宁德时代(300750) | 427.84 | +1.84% | 4.04% | 持有,止损400止盈460 |",
+5
View File
@@ -66,6 +66,11 @@
"content": "**XD紫金矿(601899) 现价25.10** | 距止损24.48仅2.5%,上周板块能源金属-6.38%领跌,若工业金属继续承压则开盘可能触发止损。**设预警24.50**", "content": "**XD紫金矿(601899) 现价25.10** | 距止损24.48仅2.5%,上周板块能源金属-6.38%领跌,若工业金属继续承压则开盘可能触发止损。**设预警24.50**",
"report_id": "cron_99c06255590a_2026-06-29_08-37-43" "report_id": "cron_99c06255590a_2026-06-29_08-37-43"
}, },
{
"time": "2026-07-02T08:55:30.266659",
"content": "- **紫金矿业(601899)** 25.47 / 止损23.07 — 避险情绪利好黄金,26附近考虑减仓",
"report_id": "cron_99c06255590a_2026-07-02_08-32-48"
},
{ {
"time": "2026-06-01T10:25:54.419132", "time": "2026-06-01T10:25:54.419132",
"content": "2. **紫金矿业(601899)** 进入加仓区间29-30,可考虑分批加仓", "content": "2. **紫金矿业(601899)** 进入加仓区间29-30,可考虑分批加仓",
+5
View File
@@ -91,6 +91,11 @@
"content": "长芯博创(300548) @281.99 +21.83% 放量走强持有,止损261.71;辽宁成大(600739) @10.09 -17.88% 弱撑10.0待企稳;海博思创(688411) @281", "content": "长芯博创(300548) @281.99 +21.83% 放量走强持有,止损261.71;辽宁成大(600739) @10.09 -17.88% 弱撑10.0待企稳;海博思创(688411) @281",
"report_id": "cron_99c06255590a_2026-06-19_08-32-54" "report_id": "cron_99c06255590a_2026-06-19_08-32-54"
}, },
{
"time": "2026-07-02T08:55:30.266659",
"content": "**海博思创(688411)** — 现价263.03 | 昨日-9.67%放量暴跌,距止损246.94仅6.5%。若今日续跌破255需立即止损。",
"report_id": "cron_99c06255590a_2026-07-02_08-32-48"
},
{ {
"time": "2026-06-01T10:25:54.419132", "time": "2026-06-01T10:25:54.419132",
"content": "1. **海博思创(688411)** 暴跌-5.95%破止损价¥255,需关注明日是否止损", "content": "1. **海博思创(688411)** 暴跌-5.95%破止损价¥255,需关注明日是否止损",
+5
View File
@@ -10,6 +10,11 @@
"time": "2026-06-01T11:55:35.956320", "time": "2026-06-01T11:55:35.956320",
"content": "• **688630|芯碁微装|345.68|+3.19%|建议持有观察【短线】|小幅突破,趋势向上,关注350关口**", "content": "• **688630|芯碁微装|345.68|+3.19%|建议持有观察【短线】|小幅突破,趋势向上,关注350关口**",
"report_id": "cron_d3797d924ddc_2026-06-01_11-31-32" "report_id": "cron_d3797d924ddc_2026-06-01_11-31-32"
},
{
"time": "2026-07-02T08:55:30.347799",
"content": "**自选关注:** 芯碁微装(688630) 497.27(-9.49%)已跌破买入区上沿556——若继续下探至430~445可考虑介入。江波龙(301308)667.84(-5.1%)仍在观察。",
"report_id": "cron_d42f2ce3b479_2026-07-01_20-14-12"
} }
] ]
} }
+5
View File
@@ -46,6 +46,11 @@
"content": "**华恒生物(688639)** 现价16.14(-2.95%) | 仓位5.25% | 止损20.03", "content": "**华恒生物(688639)** 现价16.14(-2.95%) | 仓位5.25% | 止损20.03",
"report_id": "cron_99c06255590a_2026-07-01_08-39-42" "report_id": "cron_99c06255590a_2026-07-01_08-39-42"
}, },
{
"time": "2026-07-02T08:55:30.266659",
"content": "- **华恒生物(688639)** 16.37 / 止损14.96 — 距止损8.6%,窄幅运行可持",
"report_id": "cron_99c06255590a_2026-07-02_08-32-48"
},
{ {
"time": "2026-06-01T14:55:20.378304", "time": "2026-06-01T14:55:20.378304",
"content": "• 华恒生物(688639) 23.58 | +0.47% → 🤝持有,接近止损23.18", "content": "• 华恒生物(688639) 23.58 | +0.47% → 🤝持有,接近止损23.18",
+5
View File
@@ -41,6 +41,11 @@
"content": "- **中芯国际A(688981)** 浮盈+18%仓位4.64%,距离止损132.76安全", "content": "- **中芯国际A(688981)** 浮盈+18%仓位4.64%,距离止损132.76安全",
"report_id": "cron_99c06255590a_2026-06-29_08-37-43" "report_id": "cron_99c06255590a_2026-06-29_08-37-43"
}, },
{
"time": "2026-07-02T08:55:30.266659",
"content": "- **中芯国际A(688981)** 156.31 / 止损149.85 — 浮盈+24%,费城半导-6%或拖累今日回调,守住153持有",
"report_id": "cron_99c06255590a_2026-07-02_08-32-48"
},
{ {
"time": "2026-06-01T11:55:35.956320", "time": "2026-06-01T11:55:35.956320",
"content": "• **688981|中芯国际|134.87|-3.60%|建议观望等企稳【短线】|前几日大涨后获利回吐,关注134支撑**", "content": "• **688981|中芯国际|134.87|-3.60%|建议观望等企稳【短线】|前几日大涨后获利回吐,关注134支撑**",
+127 -78
View File
@@ -1,19 +1,19 @@
{ {
"checked_at": "2026-07-01T09:00:21", "checked_at": "2026-07-02T09:00:56",
"total_active": 54, "total_active": 55,
"flagged_count": 14, "flagged_count": 17,
"flagged": [ "flagged": [
{ {
"code": "000657", "code": "000657",
"name": "中钨高新", "name": "中钨高新",
"price": 95.99, "price": 95.94,
"flags": [ "flags": [
"现价95.99在买入区94~98(是否可买需结合timing_signal判断)" "现价95.94在买入区94~98(是否可买需结合timing_signal判断)"
], ],
"age_days": 0, "age_days": 0,
"last_update": "2026-06-30 10:56", "last_update": "2026-07-01 15:00",
"entry_zone": "94~98", "entry_zone": "94~98",
"current": "盈利持有 | 目标105.13 | 止损93.58 | 买入区94.07~97.91", "current": "盈利持有 | 目标105.29 | 止损93.12 | 买入区94.02~97.86",
"updated_by": "auto", "updated_by": "auto",
"updated_reason": "自动生成", "updated_reason": "自动生成",
"is_watchlist": true "is_watchlist": true
@@ -21,59 +21,75 @@
{ {
"code": "000711", "code": "000711",
"name": "ST京蓝", "name": "ST京蓝",
"price": 4.1, "price": 4.77,
"flags": [ "flags": [
"现价4.10在买入区4~4(是否可买需结合timing_signal判断)" "现价4.77在买入区5~5(是否可买需结合timing_signal判断)"
], ],
"age_days": 0, "age_days": 0,
"last_update": "2026-06-30 10:56", "last_update": "2026-07-01 15:01",
"entry_zone": "4~4", "entry_zone": "5~5",
"current": "盈利持有 | 目标4.54 | 止损3.98 | 买入区4.02~4.18 | 信号:观望", "current": "盈利持有 | 目标5.44 | 止损4.63 | 买入区4.67~4.87 | 信号:观望",
"updated_by": "auto", "updated_by": "auto",
"updated_reason": "自动生成", "updated_reason": "自动生成",
"is_watchlist": true "is_watchlist": true
}, },
{
"code": "001309",
"name": "德明利",
"price": 893.22,
"flags": [
"现价893.22在买入区877~913(是否可买需结合timing_signal判断)"
],
"age_days": 0,
"last_update": "2026-07-01 15:01",
"entry_zone": "877~913",
"current": "盈利持有 | 止损参考858.0 | 买入区877.1~912.9",
"updated_by": "manual",
"updated_reason": "自动生成",
"is_watchlist": true
},
{ {
"code": "002594", "code": "002594",
"name": "比亚迪", "name": "比亚迪",
"price": 78.94, "price": 80.66,
"flags": [ "flags": [
"现价78.94在买入区77~80(是否可买需结合timing_signal判断)" "现价80.66在买入区79~81(是否可买需结合timing_signal判断)"
], ],
"age_days": 0, "age_days": 0,
"last_update": "2026-06-30 10:56", "last_update": "2026-07-01 15:01",
"entry_zone": "77~80", "entry_zone": "79~81",
"current": "盈利持有 | 目标85.2 | 止损73.51 | 买入区77.36~80.02 | 信号:观望", "current": "盈利持有 | ⚠️盈亏比偏低(1:1.6),谨慎买入 | 目标84.49 | 止损78.24 | 买入区79.05~80.74 | 信号:观望",
"updated_by": "auto", "updated_by": "auto",
"updated_reason": "自动生成", "updated_reason": "自动生成",
"is_watchlist": true "is_watchlist": true
}, },
{ {
"code": "00968", "code": "02318",
"name": "信义光能", "name": "中国平安",
"price": 2.04, "price": 51.05,
"flags": [ "flags": [
"现价2.04在买入区2~2(是否可买需结合timing_signal判断)" "[STRATEGY_STALE] 信号不良(timing_signal含['弱势持有'])",
"现价51.05在买入区50~51(是否可买需结合timing_signal判断)"
], ],
"age_days": 0, "age_days": 0,
"last_update": "2026-06-30 10:56", "last_update": "2026-07-01 15:01",
"entry_zone": "2~2", "entry_zone": "50~51",
"current": "盈利持有 | ⚠️盈亏比偏低(1:1.6),谨慎买入 | 目标2.23 | 止损1.92 | 买入区2.0~2.04 | 信号:关注", "current": "盈利持有 | ⚠️盈亏比偏低(1:2.0),谨慎买入 | 止损参考49.36 | 买入区50.08~51.12 | 信号:弱势持有",
"updated_by": "auto", "updated_by": "manual",
"updated_reason": "自动生成", "updated_reason": "自动生成",
"is_watchlist": true "is_watchlist": true
}, },
{ {
"code": "02359", "code": "02359",
"name": "药明康德", "name": "药明康德",
"price": 156.2, "price": 153.7,
"flags": [ "flags": [
"现价156.20在买入区153~159(是否可买需结合timing_signal判断)" "现价153.70在买入区151~157(是否可买需结合timing_signal判断)"
], ],
"age_days": 0, "age_days": 0,
"last_update": "2026-06-30 10:57", "last_update": "2026-07-01 15:01",
"entry_zone": "153~159", "entry_zone": "151~157",
"current": "盈利持有 | 目标170.5 | 止损144.56 | 买入区153.08~158.55 | 信号:买入", "current": "盈利持有 | 目标169.6 | 止损149.09 | 买入区150.63~156.77 | 信号:买入",
"updated_by": "auto", "updated_by": "auto",
"updated_reason": "自动生成", "updated_reason": "自动生成",
"is_watchlist": true "is_watchlist": true
@@ -81,14 +97,15 @@
{ {
"code": "02388", "code": "02388",
"name": "中银香港", "name": "中银香港",
"price": 42.18, "price": 42.38,
"flags": [ "flags": [
"现价42.18在买入区41~43(是否可买需结合timing_signal判断)" "[STRATEGY_STALE] 信号不良(timing_signal含['弱势持有'])",
"现价42.38在买入区42~43(是否可买需结合timing_signal判断)"
], ],
"age_days": 0, "age_days": 0,
"last_update": "2026-06-30 10:57", "last_update": "2026-07-01 15:01",
"entry_zone": "41~43", "entry_zone": "42~43",
"current": "盈利持有 | 目标46.82 | 止损39.27 | 买入区41.34~43.02 | 信号:关注", "current": "盈利持有 | 目标47.08 | 止损41.11 | 买入区41.53~43.23 | 信号:弱势持有",
"updated_by": "auto", "updated_by": "auto",
"updated_reason": "自动生成", "updated_reason": "自动生成",
"is_watchlist": true "is_watchlist": true
@@ -96,14 +113,15 @@
{ {
"code": "02628", "code": "02628",
"name": "中国人寿", "name": "中国人寿",
"price": 26.52, "price": 26.66,
"flags": [ "flags": [
"现价26.52在买入区26~27(是否可买需结合timing_signal判断)" "[STRATEGY_STALE] 信号不良(timing_signal含['弱势持有'])",
"现价26.66在买入区26~27(是否可买需结合timing_signal判断)"
], ],
"age_days": 0, "age_days": 0,
"last_update": "2026-06-30 10:57", "last_update": "2026-07-01 15:01",
"entry_zone": "26~27", "entry_zone": "26~27",
"current": "盈利持有 | 目标28.85 | 止损24.51 | 买入区25.99~26.86 | 信号:关注", "current": "盈利持有 | 目标28.96 | 止损25.86 | 买入区26.13~27.02 | 信号:弱势持有",
"updated_by": "auto", "updated_by": "auto",
"updated_reason": "自动生成", "updated_reason": "自动生成",
"is_watchlist": true "is_watchlist": true
@@ -111,14 +129,30 @@
{ {
"code": "06160", "code": "06160",
"name": "百济神州", "name": "百济神州",
"price": 168.7, "price": 170.4,
"flags": [ "flags": [
"现价168.70在买入区165~171(是否可买需结合timing_signal判断)" "现价170.40在买入区167~172(是否可买需结合timing_signal判断)"
], ],
"age_days": 0, "age_days": 0,
"last_update": "2026-06-30 10:57", "last_update": "2026-07-01 15:01",
"entry_zone": "165~171", "entry_zone": "167~172",
"current": "盈利持有 | 目标183.23 | 止损162.12 | 买入区165.33~170.56 | 信号:关注", "current": "盈利持有 | 目标183.83 | 止损165.29 | 买入区166.99~172.03",
"updated_by": "auto",
"updated_reason": "自动生成",
"is_watchlist": true
},
{
"code": "09988",
"name": "阿里巴巴-W",
"price": 92.85,
"flags": [
"[STRATEGY_STALE] 信号不良(timing_signal含['弱势持有'])",
"现价92.85在买入区91~93(是否可买需结合timing_signal判断)"
],
"age_days": 0,
"last_update": "2026-07-01 15:01",
"entry_zone": "91~93",
"current": "盈利持有 | ⚠️盈亏比偏低(1:1.6),谨慎买入 | 目标100.64 | 止损89.74 | 买入区90.99~93.04 | 信号:弱势持有",
"updated_by": "auto", "updated_by": "auto",
"updated_reason": "自动生成", "updated_reason": "自动生成",
"is_watchlist": true "is_watchlist": true
@@ -126,14 +160,29 @@
{ {
"code": "300124", "code": "300124",
"name": "汇川技术", "name": "汇川技术",
"price": 65.89, "price": 68.2,
"flags": [ "flags": [
"现价65.89在买入区65~67(是否可买需结合timing_signal判断)" "现价68.20在买入区67~70(是否可买需结合timing_signal判断)"
], ],
"age_days": 0, "age_days": 0,
"last_update": "2026-06-30 10:57", "last_update": "2026-07-01 15:01",
"entry_zone": "65~67", "entry_zone": "67~70",
"current": "盈利持有 | 目标70.99 | 止损63.91 | 买入区64.57~66.74 | 信号:观望", "current": "盈利持有 | 目标75.14 | 止损66.15 | 买入区66.84~69.56 | 信号:观望",
"updated_by": "auto",
"updated_reason": "自动生成",
"is_watchlist": true
},
{
"code": "301308",
"name": "江波龙",
"price": 667.84,
"flags": [
"现价667.84在买入区654~681(是否可买需结合timing_signal判断)"
],
"age_days": 0,
"last_update": "2026-07-01 15:02",
"entry_zone": "654~681",
"current": "盈利持有 | 目标786.56 | 止损631.16 | 买入区654.48~681.2",
"updated_by": "auto", "updated_by": "auto",
"updated_reason": "自动生成", "updated_reason": "自动生成",
"is_watchlist": true "is_watchlist": true
@@ -141,14 +190,14 @@
{ {
"code": "600519", "code": "600519",
"name": "贵州茅台", "name": "贵州茅台",
"price": 1179.45, "price": 1193.01,
"flags": [ "flags": [
"现价1179.45在买入区1156~1185(是否可买需结合timing_signal判断)" "现价1193.01在买入区1169~1205(是否可买需结合timing_signal判断)"
], ],
"age_days": 0, "age_days": 0,
"last_update": "2026-06-30 10:57", "last_update": "2026-07-01 15:02",
"entry_zone": "1156~1185", "entry_zone": "1169~1205",
"current": "盈利持有 | ⚠️盈亏比偏低(1:1.9),谨慎买入 | 目标1246.52 | 止损1144.07 | 买入区1155.86~1185.05 | 信号:关注", "current": "盈利持有 | 目标1277.36 | 止损1157.22 | 买入区1169.15~1205.28 | 信号:关注",
"updated_by": "auto", "updated_by": "auto",
"updated_reason": "自动生成", "updated_reason": "自动生成",
"is_watchlist": true "is_watchlist": true
@@ -156,14 +205,14 @@
{ {
"code": "601318", "code": "601318",
"name": "中国平安", "name": "中国平安",
"price": 47.51, "price": 49.53,
"flags": [ "flags": [
"现价47.51在买入区47~48(是否可买需结合timing_signal判断)" "现价49.53在买入区49~50(是否可买需结合timing_signal判断)"
], ],
"age_days": 0, "age_days": 0,
"last_update": "2026-06-30 10:57", "last_update": "2026-07-01 15:02",
"entry_zone": "47~48", "entry_zone": "49~50",
"current": "盈利持有 | 目标50.56 | 止损46.08 | 买入区46.56~47.87 | 信号:观望", "current": "盈利持有 | ⚠️盈亏比偏低(1:1.7),谨慎买入 | 目标52.51 | 止损47.74 | 买入区48.54~49.65 | 信号:观望",
"updated_by": "auto", "updated_by": "auto",
"updated_reason": "自动生成", "updated_reason": "自动生成",
"is_watchlist": true "is_watchlist": true
@@ -171,14 +220,14 @@
{ {
"code": "688630", "code": "688630",
"name": "芯碁微装", "name": "芯碁微装",
"price": 533.52, "price": 497.27,
"flags": [ "flags": [
"现价533.52在买入区523~544(是否可买需结合timing_signal判断)" "现价497.27在买入区487~507(是否可买需结合timing_signal判断)"
], ],
"age_days": 0, "age_days": 0,
"last_update": "2026-06-30 10:57", "last_update": "2026-07-01 15:02",
"entry_zone": "523~544", "entry_zone": "487~507",
"current": "盈利持有 | 目标590.14 | 止损516.6 | 买入区522.85~544.19", "current": "盈利持有 | 目标609.23 | 止损475.01 | 买入区487.32~507.22",
"updated_by": "auto", "updated_by": "auto",
"updated_reason": "自动生成", "updated_reason": "自动生成",
"is_watchlist": true "is_watchlist": true
@@ -186,14 +235,14 @@
{ {
"code": "688795", "code": "688795",
"name": "摩尔线程-U", "name": "摩尔线程-U",
"price": 711.67, "price": 673.8,
"flags": [ "flags": [
"现价711.67在买入区697~721(是否可买需结合timing_signal判断)" "现价673.80在买入区660~687(是否可买需结合timing_signal判断)"
], ],
"age_days": 0, "age_days": 0,
"last_update": "2026-06-30 10:57", "last_update": "2026-07-01 15:02",
"entry_zone": "697~721", "entry_zone": "660~687",
"current": "盈利持有 | 目标766.54 | 止损690.32 | 买入区697.44~720.81 | 信号:观望", "current": "盈利持有 | 目标747.74 | 止损651.23 | 买入区660.32~687.28 | 信号:观望",
"updated_by": "auto", "updated_by": "auto",
"updated_reason": "自动生成", "updated_reason": "自动生成",
"is_watchlist": true "is_watchlist": true
@@ -201,27 +250,27 @@
{ {
"code": "688802", "code": "688802",
"name": "沐曦股份-U", "name": "沐曦股份-U",
"price": 818.1, "price": 780.0,
"flags": [ "flags": [
"现价818.10在买入区802~834(是否可买需结合timing_signal判断)" "现价780.00在买入区764~796(是否可买需结合timing_signal判断)"
], ],
"age_days": 0, "age_days": 0,
"last_update": "2026-06-30 10:57", "last_update": "2026-07-01 15:02",
"entry_zone": "802~834", "entry_zone": "764~796",
"current": "盈利持有 | 目标917.32 | 止损793.56 | 买入区801.74~834.46 | 信号:买入", "current": "盈利持有 | 目标924.71 | 止损751.49 | 买入区764.4~795.6",
"updated_by": "auto", "updated_by": "auto",
"updated_reason": "自动生成", "updated_reason": "自动生成",
"is_watchlist": true "is_watchlist": true
} }
], ],
"portfolio": { "portfolio": {
"position_pct": 86.8, "position_pct": 86.65,
"cash": 92678.85, "cash": 92678.85,
"weak_position_pct": 28.6, "weak_position_pct": 28.6,
"all_weak_pct": 40.7, "all_weak_pct": 40.0,
"signals": [ "signals": [
"[PORTFOLIO_FULL] 总仓位86.8%(现金92679元),买入建议受限" "[PORTFOLIO_FULL] 总仓位86.65%(现金92679元),买入建议受限"
] ]
}, },
"summary": "扫描54个策略,14个需关注" "summary": "扫描55个策略,17个需关注"
} }
+36
View File
@@ -94,3 +94,39 @@
4. 关闭 TODO #41 4. 关闭 TODO #41
验证: 三条误报标题在修复后均不触发 HIGH 匹配。 验证: 三条误报标题在修复后均不触发 HIGH 匹配。
## 2026-07-02 修复:intraday_health_check.py 盘中自检三项BUG
**发现的问题:**
1. 缺少 `sys.path.insert(0, "/home/hmo/MoFin")``from mo_data import ...``ModuleNotFoundError: No module named 'mo_data'`(自愈执行器报告为 "name 'mo_data' is not defined"
2. `check_xiaoguo()``urllib.request.urlopen("http://node122:18003")` 在主机不可达时无限hang住(TCP SYN被防火墙丢,Python timeout失效),导致整个盘中自检超时
3. `datetime.strptime` 格式 `"%Y-%m-%d %H:%M"``read_portfolio()` 返回的 `updated_at`(含秒:`"%Y-%m-%d %H:%M:%S"`)不匹配 → 解析Exception
**修改内容:**
- `/home/hmo/MoFin/scripts/intraday_health_check.py`
- 添加 `import socket``sys.path.insert(0, "/home/hmo/MoFin")`
- `check_xiaoguo()`: 用 `socket.settimeout(3)` 替换 `urllib` HTTP检查,防止hang死
- `check_price_monitor()`: 将 `strptime` 格式从 `"%Y-%m-%d %H:%M"` 改为 `"%Y-%m-%d %H:%M:%S"`
- `check_http()`: 默认timeout从8秒降至5秒(加强健壮性)
**效果预期:**
- 盘中自检不再因 `mo_data` 导入失败而报错
- 盘中自检不再因 `node122` 不可达而超时hang死
- 价格新鲜度检查正确解析 `updated_at` 时间戳
- 相关TODO#48, #52)已标记resolved
**发现的问题:**
1. price_monitor.py 的 refresh_data_prices() 在 DB 持仓价格为 NULL 时崩溃。`s.get('price', 0)` 在 key 存在但值为 None 时返回 None(不是 0),导致 `abs(None - price)` 触发 TypeError。
2. 港股备用通道(fetch_hk_eastmoney_fallback)每只港股有 1 秒 delay09:30 开盘前港股 API 返回 0 价格,全部 HK 股票走降级通道空耗 ~14 秒。
3. Hermes cron 版(profile/scripts/price_monitor.py)与系统 crontab 版(MoFin/price_monitor.py)并存,系统 crontab 每次运行会覆盖 JSON 文件。
**修改内容:**
- `/home/hmo/.hermes/profiles/position-analyst/scripts/price_monitor.py`
- 第 335-337 行:`old = s.get('price'); if old is None: old = 0` — 处理 DB NULL 价格
- 第 377-379 行:同上,watchlist 更新部分
- 第 305-311 行:港股降级通道增加 09:30 开盘检查,开盘前跳过
**效果预期:**
- Hermes cron 版 price_monitor 不会再因 NULL 价格崩溃,DB 已更新 11 只 A 股持仓价格
- 港股开盘前不会再空耗 14+ 秒走东财降级通道
- 盘中健康检查下次运行时将看到新鲜数据,不再误报
View File
+3 -2
View File
@@ -27,9 +27,9 @@ DB_PATH = DATA_DIR / "mofin.db"
# ═══════════════════════════════════════════════════════════ # ═══════════════════════════════════════════════════════════
def get_conn() -> sqlite3.Connection: def get_conn() -> sqlite3.Connection:
"""获取数据库连接(WAL 模式,外键约束,Row 工厂)""" """获取数据库连接(WAL 模式,外键约束,Row 工厂5秒超时防并发锁"""
DATA_DIR.mkdir(parents=True, exist_ok=True) DATA_DIR.mkdir(parents=True, exist_ok=True)
conn = sqlite3.connect(str(DB_PATH)) conn = sqlite3.connect(str(DB_PATH), timeout=5)
conn.row_factory = sqlite3.Row conn.row_factory = sqlite3.Row
conn.execute("PRAGMA journal_mode=WAL") conn.execute("PRAGMA journal_mode=WAL")
conn.execute("PRAGMA foreign_keys=ON") conn.execute("PRAGMA foreign_keys=ON")
@@ -677,6 +677,7 @@ def query_holdings(conn: sqlite3.Connection) -> list[dict]:
"""持仓列表(含最新策略)""" """持仓列表(含最新策略)"""
rows = conn.execute(""" rows = conn.execute("""
SELECT h.code, h.name, h.shares, h.cost, h.position_pct, h.is_active, SELECT h.code, h.name, h.shares, h.cost, h.position_pct, h.is_active,
h.price, h.change_pct, h.currency,
hs.stop_loss, hs.take_profit, hs.entry_low, hs.entry_high, hs.stop_loss, hs.take_profit, hs.entry_low, hs.entry_high,
hs.reason as action, hs.created_at as strategy_updated hs.reason as action, hs.created_at as strategy_updated
FROM holdings h FROM holdings h
+4 -4
View File
@@ -211,14 +211,14 @@ def refresh_data_prices():
# 收集所有需要拉取的代码 # 收集所有需要拉取的代码
try: try:
pf = mo_data.read_portfolio() pf = read_portfolio()
for s in pf.get('holdings', []): for s in pf.get('holdings', []):
all_codes.add(s['code']) all_codes.add(s['code'])
except: except:
pf = {"holdings": []} pf = {"holdings": []}
try: try:
wl = mo_data.read_watchlist() wl = read_watchlist()
for s in wl.get('stocks', []): for s in wl.get('stocks', []):
all_codes.add(s['code']) all_codes.add(s['code'])
except: except:
@@ -363,7 +363,7 @@ def _branch_alert_suffix(code, price, shares=0, cost=0):
def _record_branch_trigger(code, branch_id, price): def _record_branch_trigger(code, branch_id, price):
"""记录分支触发事件(自成长:trigger_count+1""" """记录分支触发事件(自成长:trigger_count+1"""
try: try:
raw = mo_data.read_decisions() raw = read_decisions()
for d in raw.get('decisions', []): for d in raw.get('decisions', []):
if d.get('code') == code and d.get('strategy_tree',{}).get('branches'): if d.get('code') == code and d.get('strategy_tree',{}).get('branches'):
for b in d['strategy_tree']['branches']: for b in d['strategy_tree']['branches']:
@@ -487,7 +487,7 @@ def run_once(round_label=""):
_SCENARIO_CACHE = detect_scenario() if HAS_TREE else {} _SCENARIO_CACHE = detect_scenario() if HAS_TREE else {}
_BRANCH_CACHE = {} _BRANCH_CACHE = {}
try: try:
raw = mo_data.read_decisions() raw = read_decisions()
for d in raw.get('decisions', []): for d in raw.get('decisions', []):
tree = d.get('strategy_tree', {}) tree = d.get('strategy_tree', {})
if tree and tree.get('branches'): if tree and tree.get('branches'):
+41 -9
View File
@@ -5,9 +5,12 @@
发现问题→写TODO(消费管道与每日体检共享)。 发现问题→写TODO(消费管道与每日体检共享)。
""" """
import json, os, sqlite3, subprocess, urllib.request import json, os, sqlite3, subprocess, urllib.request, sys, socket
from pathlib import Path from pathlib import Path
from datetime import datetime, timedelta from datetime import datetime, timedelta
# ── MoFin path ─────────────────────────────────────────────────────
sys.path.insert(0, "/home/hmo/MoFin")
from mo_data import read_portfolio, read_decisions, read_watchlist from mo_data import read_portfolio, read_decisions, read_watchlist
BASE = Path("/home/hmo/MoFin") BASE = Path("/home/hmo/MoFin")
@@ -37,7 +40,8 @@ def check_port(port):
return False return False
def check_http(url, timeout=8): def check_http(url, timeout=5):
"""检查HTTP可达性,5秒超时防止hang住"""
try: try:
for k in list(os.environ.keys()): for k in list(os.environ.keys()):
if 'proxy' in k.lower(): if 'proxy' in k.lower():
@@ -68,8 +72,14 @@ def check_xiaoguo():
if scans_today <= 0: if scans_today <= 0:
# 可能是小果离线了,不报严重,记录即可 # 可能是小果离线了,不报严重,记录即可
return return
# API — 不通时scanner已降级为unknown,不影响 # API — 用socket快速检测可达性(3s超时)
check_http("http://node122:18003/v1/models") try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(3)
s.connect(("node122", 18003))
s.close()
except:
pass
PORTFOLIO_PATH = str(DATA / "portfolio.json") PORTFOLIO_PATH = str(DATA / "portfolio.json")
@@ -113,11 +123,23 @@ def check_price_monitor():
return return
# 检查portfolio.json数据新鲜度 # 检查portfolio.json数据新鲜度
# 兼容 '2026-07-02 10:43'price_monitor写入,无秒)和 '2026-07-02 10:43:53'DB写入,有秒)
def _parse_updated_at(ts: str) -> datetime | None:
for fmt in ("%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M"):
try: try:
pf = mo_data.read_portfolio() return datetime.strptime(ts, fmt)
except ValueError:
continue
return None
try:
pf = read_portfolio()
pf_updated = pf.get("updated_at", "") pf_updated = pf.get("updated_at", "")
if pf_updated: if pf_updated:
pf_dt = datetime.strptime(pf_updated, "%Y-%m-%d %H:%M") pf_dt = _parse_updated_at(pf_updated)
if pf_dt is None:
log(False, f"价格数据updated_at格式无法解析: {pf_updated}")
else:
seconds_ago = (datetime.now() - pf_dt).total_seconds() seconds_ago = (datetime.now() - pf_dt).total_seconds()
if seconds_ago < 600: # 10分钟内 if seconds_ago < 600: # 10分钟内
log(True, f"价格监控运行正常,数据{int(seconds_ago//60)}分钟前更新") log(True, f"价格监控运行正常,数据{int(seconds_ago//60)}分钟前更新")
@@ -171,7 +193,8 @@ def check_signal_pipeline():
if summary: if summary:
reason = summary[:80].replace("\n", " ") reason = summary[:80].replace("\n", " ")
if level == "high" and not expired: if level == "high" and not expired:
log(False, f"🔴 宏观风险HIGH: {reason}") reason_clean = reason.replace("【高风险】", "").strip()[:60]
log(False, f"🔴 宏观风险HIGH: {reason_clean}")
elif level == "high" and expired: elif level == "high" and expired:
log(True, f"⏳ 宏观风险HIGH已过期(无新信号超过15分钟)") log(True, f"⏳ 宏观风险HIGH已过期(无新信号超过15分钟)")
elif level == "medium": elif level == "medium":
@@ -188,8 +211,17 @@ def write_todos():
for msg in ISSUES: for msg in ISSUES:
title = f"[盘中自检] {msg}" title = f"[盘中自检] {msg}"
try: try:
conn = sqlite3.connect(str(DB_PATH)) conn = sqlite3.connect(str(DB_PATH), timeout=10)
exist = conn.execute("SELECT id FROM todos WHERE title=? AND status IN ('pending','in_progress')", (title,)).fetchone() conn.execute("PRAGMA busy_timeout=5000")
# 宏观风险HIGH去重:只要有pending/in_progress的宏观风险TODO,不再新增
if "宏观风险HIGH" in msg:
exist = conn.execute(
"SELECT id FROM todos WHERE title LIKE '%宏观风险HIGH%' AND status IN ('pending','in_progress') LIMIT 1"
).fetchone()
else:
exist = conn.execute(
"SELECT id FROM todos WHERE title=? AND status IN ('pending','in_progress')", (title,)
).fetchone()
if not exist: if not exist:
conn.execute( conn.execute(
"INSERT INTO todos (title, description, priority, source, status, fix_action) " "INSERT INTO todos (title, description, priority, source, status, fix_action) "
+4 -3
View File
@@ -40,8 +40,8 @@ HIGH_PATTERNS = [
r"fed.*(?:emergency|unexpected|surprise|hike|cut)", r"fed.*(?:emergency|unexpected|surprise|hike|cut)",
# 指数暴跌(需 ≥2% 跌幅或使用更强范围词) # 指数暴跌(需 ≥2% 跌幅或使用更强范围词)
r"指数[^。]*?(?:暴跌|熔断|闪崩|重挫)", r"指数[^。]*?(?:暴跌|熔断|闪崩|重挫)",
r"指数[^。]*?(?:跌幅|下跌)[^。]*?[2-9]%", r"指数[^。]*?(?:跌幅[^。]{0,20}(?:扩大至|达|至|超|为|逾)[^。]*?(?<![0-9.])(?:[2-9]|[1-9][0-9])(?:\.\d+)?%|下跌(?!.*?涨)[^。]*?(?<![0-9.])(?:[2-9]|[1-9][0-9])(?:\.\d+)?%)",
r"(?:暴跌|重挫|熔断).*[5-9]%", r"(?:暴跌|重挫|熔断).*?(?<![0-9.])(?:[5-9]|[1-9][0-9])(?:\.\d+)?%",
r"熔断|闪崩", r"熔断|闪崩",
# 地缘+贸易 # 地缘+贸易
r"关税.*(?:升级|新|报复|制裁)", r"关税.*(?:升级|新|报复|制裁)",
@@ -82,7 +82,7 @@ MEDIUM_PATTERNS = [
# 旧版有 银行.*倒闭|挤兑|破产 , 新版有 银行.*(?:倒闭|挤兑|破产 # 旧版有 银行.*倒闭|挤兑|破产 , 新版有 银行.*(?:倒闭|挤兑|破产
_PATTERN_CHECKS = { _PATTERN_CHECKS = {
8: ["暴跌|熔断|闪崩|重挫"], # index pattern must use strong crash words, not "跌幅" 8: ["暴跌|熔断|闪崩|重挫"], # index pattern must use strong crash words, not "跌幅"
9: ["[2-9]%"], # 指数+跌幅 requires ≥2% 9: ["(?<![0-9.])", "(?:扩大至|达|至|超|为|逾)"], # new: negative lookbehind for decimals + measurement words for 跌幅
14: ["核(?:威胁", "核威胁|武器|弹头"], # must NOT have standalone 核 14: ["核(?:威胁", "核威胁|武器|弹头"], # must NOT have standalone 核
18: ["倒闭|挤兑|破产"], # bank pattern must have crisis keywords 18: ["倒闭|挤兑|破产"], # bank pattern must have crisis keywords
19: ["金融危机(?:风险", "危机|债务危机"], # must NOT have standalone 金融危机 19: ["金融危机(?:风险", "危机|债务危机"], # must NOT have standalone 金融危机
@@ -90,6 +90,7 @@ _PATTERN_CHECKS = {
_KNOWN_BAD_SIGS = { _KNOWN_BAD_SIGS = {
# Known stale .pyc signature fragments that indicate wrong version # Known stale .pyc signature fragments that indicate wrong version
"指数.*跌幅": "旧版用 .* 跨句匹配且无 ≥2% 阈值", "指数.*跌幅": "旧版用 .* 跨句匹配且无 ≥2% 阈值",
"[2-9]%(?!\")": "旧版 pattern 9 无上下文限制和阈值修复(新版用 (?:[2-9]|[1-9][0-9])(?:\\.\\d+)?% 替代 [2-9]%",
"|核|": "旧版有独立单字核", "|核|": "旧版有独立单字核",
"英伟达|nvidia.*跌": "旧版 alternation 分组错误", "英伟达|nvidia.*跌": "旧版 alternation 分组错误",
"导弹.*发射": "旧版只匹配发射不匹配袭击", "导弹.*发射": "旧版只匹配发射不匹配袭击",
+4 -4
View File
@@ -279,14 +279,14 @@ def refresh_data_prices():
# 收集所有需要拉取的代码 # 收集所有需要拉取的代码
try: try:
pf = mo_data.read_portfolio() pf = read_portfolio()
for s in pf.get('holdings', []): for s in pf.get('holdings', []):
all_codes.add(s['code']) all_codes.add(s['code'])
except: except:
pf = {"holdings": []} pf = {"holdings": []}
try: try:
wl = mo_data.read_watchlist() wl = read_watchlist()
for s in wl.get('stocks', []): for s in wl.get('stocks', []):
all_codes.add(s['code']) all_codes.add(s['code'])
except: except:
@@ -436,7 +436,7 @@ def _branch_alert_suffix(code, price, shares=0, cost=0):
def _record_branch_trigger(code, branch_id, price): def _record_branch_trigger(code, branch_id, price):
"""记录分支触发事件(自成长:trigger_count+1""" """记录分支触发事件(自成长:trigger_count+1"""
try: try:
raw = mo_data.read_decisions() raw = read_decisions()
for d in raw.get('decisions', []): for d in raw.get('decisions', []):
if d.get('code') == code and d.get('strategy_tree',{}).get('branches'): if d.get('code') == code and d.get('strategy_tree',{}).get('branches'):
for b in d['strategy_tree']['branches']: for b in d['strategy_tree']['branches']:
@@ -560,7 +560,7 @@ def run_once(round_label=""):
_SCENARIO_CACHE = detect_scenario() if HAS_TREE else {} _SCENARIO_CACHE = detect_scenario() if HAS_TREE else {}
_BRANCH_CACHE = {} _BRANCH_CACHE = {}
try: try:
raw = mo_data.read_decisions() raw = read_decisions()
for d in raw.get('decisions', []): for d in raw.get('decisions', []):
tree = d.get('strategy_tree', {}) tree = d.get('strategy_tree', {})
if tree and tree.get('branches'): if tree and tree.get('branches'):
+8 -6
View File
@@ -44,9 +44,11 @@ def _http_get(url, headers=None, timeout=10):
def _detect_market(code): def _detect_market(code):
"""自动识别A股/港股""" """自动识别A股/港股
A股代码固定6位,港股代码5位(含前缀0如00700)。
"""
code = str(code).strip() code = str(code).strip()
if code.startswith("0") or code.startswith("3") or len(code) == 6: if len(code) == 6:
return "ashare" return "ashare"
if len(code) <= 5: if len(code) <= 5:
return "hk" return "hk"
@@ -337,10 +339,10 @@ def _sina_hk(code):
return { return {
"code": code, "code": code,
"name": name, "name": name,
"price": price, "price": round(prev_close + change_amt, 2) if prev_close > 0 and abs(change_amt) > 0 else price,
"change_pct": change_pct, "change_pct": change_pct,
"high": float(fields[5]) if fields[5] else None, "high": None, # Sina HK format不含high/low字段
"low": float(fields[6]) if fields[6] else None, "low": None,
"open": float(fields[4]) if fields[4] else None, "open": float(fields[4]) if fields[4] else None,
"prev_close": prev_close, "prev_close": prev_close,
"volume": None, "volume": None,
@@ -366,7 +368,7 @@ def _tencent_hk(code):
prev_close = float(fields[4]) if fields[4] else 0 prev_close = float(fields[4]) if fields[4] else 0
if price <= 0: if price <= 0:
return None return None
change_pct = float(fields[7]) if len(fields) > 7 and fields[7] else 0 change_pct = round((price - prev_close) / prev_close * 100, 2) if prev_close > 0 else None
return { return {
"code": code, "code": code,
"name": name, "name": name,
+200 -2
View File
@@ -20,6 +20,174 @@ import multi_timeframe as mtf
from mo_data import read_portfolio, read_decisions, read_watchlist from mo_data import read_portfolio, read_decisions, read_watchlist
from strategy_tree import detect_scenario from strategy_tree import detect_scenario
# ─── 策略准入门禁 — 硬性质量红线 ───────────────────────────────
# 每一条策略写入前必须过此门禁。不过的不得写入DB/JSON,
# 必须触发重评修复。代码层面硬拦截,不依赖prompt或文档。
#
# 规则列表 + 严重程度 + 修复建议
STRATEGY_QUALITY_GATES = [
{
"id": "GATE_LOSS_EXISTS",
"desc": "止损必须存在且>0",
"check": lambda d: (d.get("stop_loss") or 0) > 0,
"severity": "CRITICAL",
"fix": "调用 technical_analysis 计算支撑位设置止损"
},
{
"id": "GATE_PROFIT_EXISTS",
"desc": "止盈必须存在且>0(纯自选股可放宽)",
"check": lambda d: (d.get("take_profit") or 0) > 0,
"severity": "CRITICAL",
"fix": "调用 technical_analysis 计算阻力位设置止盈目标"
},
{
"id": "GATE_SL_GTE_LOW",
"desc": "止损必须 ≤ 买入区下沿",
"check": lambda d: (d.get("stop_loss") or 0) <= (d.get("entry_low") or 99999),
"severity": "HIGH",
"fix": "止损不能高于买入区,调整止损至买入区以下"
},
{
"id": "GATE_ENTRY_RANGE",
"desc": "买入区下沿 < 上沿",
"check": lambda d: (d.get("entry_low") or 0) < (d.get("entry_high") or 0),
"severity": "CRITICAL",
"fix": "entry_low=现价×0.95, entry_high=现价×1.05 取近似区间"
},
{
"id": "GATE_RR_COMPUTED",
"desc": "买入推荐必须含RR",
"check": lambda d: not ("买入" in (d.get("timing_signal") or "") or "加仓" in (d.get("timing_signal") or "")) or (d.get("rr_ratio") or 0) > 0,
"severity": "HIGH",
"fix": "RR = (止盈-现价)/(现价-止损),数据齐全后自动算"
},
{
"id": "GATE_RR_MINIMUM",
"desc": "买入推荐RR≥1.5(非买入信号跳过)",
"check": lambda d: not ("买入" in (d.get("timing_signal") or "") or "加仓" in (d.get("timing_signal") or "")) or (d.get("rr_ratio") or 0) >= 1.5,
"severity": "HIGH",
"fix": "RR不足→signal降级为'信号不充分',不进推荐区"
},
{
"id": "GATE_SIGNAL_SHORT",
"desc": "timing_signal 必须是短词(2-4字)",
"check": lambda d: len((d.get("timing_signal") or "").strip().split()) <= 4 and (d.get("timing_signal") or "") not in ("neutral", ""),
"severity": "MEDIUM",
"fix": "使用短词:买入/加仓/观望/持有/关注/信号不充分"
},
{
"id": "GATE_TECH_SNAPSHOT",
"desc": "tech_snapshot 必须包含技术位数值",
"check": lambda d: bool(d.get("tech_snapshot")) and any(c in d["tech_snapshot"] for c in "支撑阻力压强"),
"severity": "MEDIUM",
"fix": "tech_snapshot 包含强撑/弱撑/弱压/强压至少3个数值"
},
{
"id": "GATE_CURRENCY_SET",
"desc": "港股必须标 currency=HKD",
"check": lambda d: not (len(str(d.get("code",""))) == 5 and str(d.get("code",""))[0] in "01") or d.get("currency") == "HKD",
"severity": "HIGH",
"fix": "设置 d['currency']='HKD'"
},
]
def _hk_stock(code):
return bool(len(str(code)) == 5 and str(code)[0] in ('0','1'))
def _is_buy_signal_str(signal):
"""买入/加仓/建仓类信号"""
if not signal:
return False
return any(kw in signal for kw in ["买入", "加仓", "建仓"])
# _is_buy_signal is defined later in this file (~line 1240)
def validate_strategy(d, debug=True):
"""策略评审:硬性门禁检查
返回 (passed: bool, failures: list)
任一 CRITICAL 失败 → 拒绝写入,标记 TODO 触发重评
任一 HIGH 失败 → 标记 quality_check=failed,写入但不出现在推荐区
MEDIUM 失败 → 记录但不拦截
"""
failures = []
for gate in STRATEGY_QUALITY_GATES:
try:
ok = gate["check"](d)
except Exception as e:
ok = False
if debug:
print(f" [VALIDATE] {gate['id']} 检查异常: {e}", flush=True)
if not ok:
failures.append(gate)
if debug:
print(f" [VALIDATE] ✗ {gate['id']} ({gate['severity']}): {gate['desc']}", flush=True)
passed = all(f["severity"] != "CRITICAL" for f in failures)
if debug:
criticals = [f for f in failures if f["severity"] == "CRITICAL"]
highs = [f for f in failures if f["severity"] == "HIGH"]
if passed:
print(f" [VALIDATE] ✅ 通过 ({len(failures)}条警告)" if failures else " [VALIDATE] ✅ 全通过", flush=True)
else:
print(f" [VALIDATE] ❌ {len(criticals)}条CRITICAL未通过 → 拒绝写入", flush=True)
return passed, failures
def enforce_strategy_quality(code, name, result):
"""策略写入前的强制质量门禁
对 result 执行 validate_strategy,不通过则:
- 设置 quality_check: failed + 失败原因列表
- 自动在 changelog 记录
- 返回 False,调用方不写入
- 返回 True 但 result 被修改(标记了 failed,未被写入)
"""
passed, failures = validate_strategy(result)
if not passed:
critical_issues = [f["id"] for f in failures if f["severity"] == "CRITICAL"]
high_issues = [f["id"] for f in failures if f["severity"] == "HIGH"]
# 标记质量失败
result["quality_check"] = "failed"
result["quality_issues"] = {
"critical": critical_issues,
"high": high_issues,
"all": [f["id"] for f in failures],
}
result["quality_checked_at"] = datetime.now().strftime("%Y-%m-%d %H:%M")
# 记录 changelog
cl = result.setdefault("changelog", [])
cl.append({
"time": datetime.now().strftime("%Y-%m-%d %H:%M"),
"event": f"质量门禁拒绝 (failed: {critical_issues})",
})
# 信号降级
result["status"] = "review_needed"
result["timing_signal"] = "信号不充分"
print(f" 🚫 {name}({code}) 质量门禁未通过 ({critical_issues}) → 已标记 review_needed", flush=True)
return False
# 如果有 HIGH 级别失败 → 标记但不拦截写入
high_fails = [f for f in failures if f["severity"] == "HIGH"]
if high_fails:
result["quality_check"] = "warning"
result["quality_issues"] = {"high": [f["id"] for f in high_fails]}
result["quality_checked_at"] = datetime.now().strftime("%Y-%m-%d %H:%M")
print(f" ⚠️ {name}({code}) 有{len(high_fails)}条HIGH警告,标记warning但已写入", flush=True)
else:
result["quality_check"] = "passed"
result["quality_checked_at"] = datetime.now().strftime("%Y-%m-%d %H:%M")
return True
def is_hk_stock(code): def is_hk_stock(code):
"""判断是否港股(港股代码5位,A股6位带前导零)""" """判断是否港股(港股代码5位,A股6位带前导零)"""
@@ -427,7 +595,13 @@ def batch_fetch_prices(codes):
"SELECT price, change_pct FROM holding_strategies WHERE code=? AND status='active' ORDER BY updated_at DESC LIMIT 1", (raw_code,) "SELECT price, change_pct FROM holding_strategies WHERE code=? AND status='active' ORDER BY updated_at DESC LIMIT 1", (raw_code,)
).fetchone() ).fetchone()
if row and row['price']: if row and row['price']:
all_results[raw_code] = (row['price'], 0, row['change_pct'] or 0) all_results[raw_code] = {
"price": row['price'],
"close": row['price'], # 用现价近似昨收,仅用于sentiment计算
"high": row['price'],
"low": row['price'],
"code": raw_code,
}
db.close() db.close()
if all_results: if all_results:
return all_results return all_results
@@ -1602,6 +1776,9 @@ def reassess_with_context(code, name, price, cost, shares, current_action,
except Exception: except Exception:
pass pass
# ── 策略质量门禁 ──
enforce_strategy_quality(code, name, result)
return result return result
@@ -2156,6 +2333,23 @@ def regenerate_all(stdout=True):
if added_to_wl and stdout: if added_to_wl and stdout:
print(f" 清仓→自选自动加入: {', '.join(added_to_wl)}") print(f" 清仓→自选自动加入: {', '.join(added_to_wl)}")
# 重新计算 portfolio 汇总(保留已存在的 cash,用最新价格算市值)
try:
total_mv = 0.0
for h in existing_pf.get('holdings', []):
p = h.get('price') or 0
s = h.get('shares') or 0
total_mv += p * s
if p and s and total_mv > 0:
h['market_value'] = round(p * s, 2)
old_cash = existing_pf.get('cash') or 80476 # fallback 6/23 backup
existing_pf['cash'] = old_cash
existing_pf['total_mv'] = round(total_mv, 2)
existing_pf['total_assets'] = round(total_mv + old_cash, 2)
existing_pf['position_pct'] = round(total_mv / (total_mv + old_cash) * 100, 2) if (total_mv + old_cash) > 0 else 0
except Exception as e:
print(f" [汇总计算失败] {e}", flush=True)
# DB 写入(替代 JSON dump — 强制币种约束) # DB 写入(替代 JSON dump — 强制币种约束)
try: try:
from mofin_db import get_conn, write_holdings_batch, write_portfolio_summary, write_watchlist_stock, write_holding_strategy from mofin_db import get_conn, write_holdings_batch, write_portfolio_summary, write_watchlist_stock, write_holding_strategy
@@ -2166,7 +2360,11 @@ def regenerate_all(stdout=True):
s.setdefault('currency', 'CNY') s.setdefault('currency', 'CNY')
write_watchlist_stock(conn, s) write_watchlist_stock(conn, s)
for d in decisions: for d in decisions:
write_holding_strategy(conn, d.get('code', ''), d.get('name', ''), d) # ── 策略质量门禁 ──
code = d.get('code', '')
name = d.get('name', '')
enforce_strategy_quality(code, name, d)
write_holding_strategy(conn, code, name, d)
conn.close() conn.close()
except Exception as e: except Exception as e:
print(f" [DB写入失败] {e}", flush=True) print(f" [DB写入失败] {e}", flush=True)
+8 -8
View File
@@ -390,15 +390,15 @@ def full_analysis(code):
result = { result = {
"quote": { "quote": {
"name": q["name"], "name": q.get("name", code),
"price": q["price"], "price": q["price"],
"change_pct": q["change_pct"], "change_pct": q.get("change_pct", 0),
"open": q["open"], "open": q.get("open", 0),
"high": q["high"], "high": q.get("high", 0),
"low": q["low"], "low": q.get("low", 0),
"close_yest": q["close_yest"], "close_yest": q.get("close_yest", 0),
"volume": q["volume"], "volume": q.get("volume", 0),
"amplitude": q["amplitude"], "amplitude": q.get("amplitude", 0),
}, },
"support_resistance": sr, "support_resistance": sr,
"candlestick": candle, "candlestick": candle,