diff --git a/branch_scanner.py b/branch_scanner.py index 414ccfe..6bacac3 100644 --- a/branch_scanner.py +++ b/branch_scanner.py @@ -61,7 +61,7 @@ def save_decisions(data): def check_condition(branch, scenario_id, price): - """检查分支条件是否满足""" + """检查分支条件是否满足 — 同步 strategy_tree._check_branch_condition 逻辑""" cond = branch.get("condition", {}) required_scenario = cond.get("scenario", "") if required_scenario and required_scenario != scenario_id: @@ -76,6 +76,18 @@ def check_condition(branch, scenario_id, price): if op == ">" and not (price > val): return False if op == "<=" and not (price <= val): return False if op == ">=" and not (price >= val): return False + + # 买入区下界(price_lower)检查 — 之前遗漏 + price_lower = cond.get("price_lower", "") + if price_lower and price: + ops = re.findall(r"([<>=!]+)\s*([\d.]+)", price_lower) + for op, val_str in ops: + val = float(val_str) + if op == "<" and not (price < val): return False + if op == ">" and not (price > val): return False + if op == "<=" and not (price <= val): return False + if op == ">=" and not (price >= val): return False + return True @@ -114,11 +126,17 @@ def main(): if not price: continue - for br in branches: + # 找出所有适用的分支,选最优(优先级数字最低) + best = None + for br in sorted(branches, key=lambda b: b.get("priority", 999)): if check_condition(br, sid, price): - br["trigger_count"] = br.get("trigger_count", 0) + 1 - br["last_triggered"] = today - triggered.append((code, entry.get("name", ""), br)) + best = br + break + + if best: + best["trigger_count"] = best.get("trigger_count", 0) + 1 + best["last_triggered"] = today + triggered.append((code, entry.get("name", ""), best)) if triggered: save_decisions(data) diff --git a/data/decisions.json b/data/decisions.json index a4341ca..5ba255e 100644 --- a/data/decisions.json +++ b/data/decisions.json @@ -83,9 +83,9 @@ }, "priority": 1, "rationale": "价格回调到支撑区,弱势市场低吸", - "trigger_count": 0, + "trigger_count": 1, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" }, { "id": "000657_breakout_chase", @@ -147,9 +147,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" } ], "initialized_at": "2026-06-24T10:23:51.371434" @@ -226,9 +226,9 @@ }, "priority": 1, "rationale": "价格回调到支撑区,弱势市场低吸", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" }, { "id": "000700_breakout_chase", @@ -290,9 +290,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 0, + "trigger_count": 1, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" } ], "initialized_at": "2026-06-24T10:23:51.374072" @@ -411,9 +411,9 @@ }, "priority": 0, "rationale": "止损保护本金", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" }, { "id": "000711_buy_dip", @@ -430,9 +430,9 @@ }, "priority": 1, "rationale": "价格回调到支撑区,弱势市场低吸", - "trigger_count": 3, + "trigger_count": 4, "success_rate": null, - "last_triggered": "2026-06-24T10:23:51.378572" + "last_triggered": "2026-06-24" }, { "id": "000711_breakout_chase", @@ -494,9 +494,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 3, + "trigger_count": 4, "success_rate": null, - "last_triggered": "2026-06-24T10:23:51.378572" + "last_triggered": "2026-06-24" } ], "last_evaluated": "2026-06-24T10:23:51.378572" @@ -705,9 +705,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" } ], "initialized_at": "2026-06-24T10:23:51.378593" @@ -716,17 +716,17 @@ { "code": "002594", "name": "比亚迪", - "price": 83.23, + "price": 83.03, "cost": 0, "shares": 0, "avg_price": 0, - "action": "盈利持有 | 目标92.39 | 止损80.73 | 买入区81.57~84.89 | 信号:观望", - "stop_loss": 80.73, - "entry_low": 81.57, - "entry_high": 84.89, - "tech_snapshot": "形态:光头光脚阴线/bearish 量价:主动卖盘占优 强撑:76.5 弱撑:82.74 弱压:85.0 强压:92.39", + "action": "盈利持有 | 目标92.47 | 止损80.54 | 买入区81.37~84.69 | 信号:观望", + "stop_loss": 80.54, + "entry_low": 81.37, + "entry_high": 84.69, + "tech_snapshot": "形态:光头光脚阴线/bearish 量价:主动卖盘占优 强撑:76.5 弱撑:82.45 弱压:85.0 强压:92.47", "timing_signal": "观望", - "rr_ratio": 3.66, + "rr_ratio": 3.79, "status": "updated", "note": "", "timestamp": "2026-06-24 09:00", @@ -738,7 +738,7 @@ "position_advice": "减仓或观望", "time_horizon": "观望", "created_at": "2026-06-18 17:15", - "take_profit": 92.39, + "take_profit": 92.47, "updated_reason": "技术信号变化: 大盘中性,行业偏弱,蓝筹,放量下跌,等企稳再入: 止损83.36→79.15 | 形态:带上影阴线/bearish 量价:主动卖盘占优 强撑:78.83 弱撑:83.73 弱压:87.59 强压:93.", "changelog": [ { @@ -824,7 +824,7 @@ { "id": "002594_stop_loss", "condition": { - "price": "<80.73" + "price": "<80.54" }, "action": { "type": "sell", @@ -841,26 +841,26 @@ "id": "002594_buy_dip", "condition": { "scenario": "weak_consolidation", - "price": "<=84.89", - "price_lower": ">=81.57" + "price": "<=84.69", + "price_lower": ">=81.37" }, "action": { "type": "buy", "amount": "normal", - "limit": 81.57, + "limit": 81.37, "reason": "回调支撑买入" }, "priority": 1, "rationale": "价格回调到支撑区,弱势市场低吸", - "trigger_count": 3, + "trigger_count": 2, "success_rate": null, - "last_triggered": "2026-06-24T10:23:51.382837" + "last_triggered": "2026-06-24" }, { "id": "002594_breakout_chase", "condition": { "scenario": "bullish_recovery", - "price": ">=92.39" + "price": ">=92.47" }, "action": { "type": "buy", @@ -894,7 +894,7 @@ { "id": "002594_take_profit", "condition": { - "price": ">=92.39" + "price": ">=92.47" }, "action": { "type": "sell", @@ -916,9 +916,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 3, + "trigger_count": 0, "success_rate": null, - "last_triggered": "2026-06-24T10:23:51.382837" + "last_triggered": null } ], "last_evaluated": "2026-06-24T10:23:51.382837" @@ -4831,9 +4831,9 @@ }, "priority": 1, "rationale": "价格回调到支撑区,弱势市场低吸", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" }, { "id": "300035_breakout_chase", @@ -4895,9 +4895,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 0, + "trigger_count": 1, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" } ], "initialized_at": "2026-06-24T10:23:51.430733" @@ -4906,17 +4906,17 @@ { "code": "300124", "name": "汇川技术", - "price": 66.98, + "price": 67.09, "cost": 0, "shares": 0, "avg_price": 0, - "action": "盈利持有 | 目标73.24 | 止损64.97 | 买入区65.64~68.28 | 信号:观望", - "stop_loss": 64.97, - "entry_low": 65.64, - "entry_high": 68.28, - "tech_snapshot": "形态:锤子线/T字线/bullish 量价:主动卖盘占优 强撑:60.36 弱撑:66.1 弱压:67.67 强压:73.24", + "action": "盈利持有 | 目标73.27 | 止损65.08 | 买入区65.75~68.36 | 信号:观望", + "stop_loss": 65.08, + "entry_low": 65.75, + "entry_high": 68.36, + "tech_snapshot": "形态:锤子线/T字线/bullish 量价:主动卖盘占优 强撑:60.39 弱撑:66.18 弱压:67.75 强压:73.27", "timing_signal": "观望", - "rr_ratio": 3.11, + "rr_ratio": 3.07, "status": "updated", "note": "", "timestamp": "2026-06-24 09:01", @@ -4928,7 +4928,7 @@ "position_advice": "减仓或观望", "time_horizon": "观望", "created_at": "2026-06-18 17:15", - "take_profit": 73.24, + "take_profit": 73.27, "updated_reason": "技术面重评: 止损65.78→64.82 | 形态:光头光脚阴线/bearish 量价:主动卖盘占优 强撑:61.61 弱撑:65.99 弱压:68.95 强压:73", "changelog": [ { @@ -5007,7 +5007,7 @@ { "id": "300124_stop_loss", "condition": { - "price": "<64.97" + "price": "<65.08" }, "action": { "type": "sell", @@ -5024,26 +5024,26 @@ "id": "300124_buy_dip", "condition": { "scenario": "weak_consolidation", - "price": "<=68.28", - "price_lower": ">=65.64" + "price": "<=68.36", + "price_lower": ">=65.75" }, "action": { "type": "buy", "amount": "normal", - "limit": 65.64, + "limit": 65.75, "reason": "回调支撑买入" }, "priority": 1, "rationale": "价格回调到支撑区,弱势市场低吸", - "trigger_count": 3, + "trigger_count": 2, "success_rate": null, - "last_triggered": "2026-06-24T10:23:51.435819" + "last_triggered": "2026-06-24" }, { "id": "300124_breakout_chase", "condition": { "scenario": "bullish_recovery", - "price": ">=73.24" + "price": ">=73.27" }, "action": { "type": "buy", @@ -5077,7 +5077,7 @@ { "id": "300124_take_profit", "condition": { - "price": ">=73.24" + "price": ">=73.27" }, "action": { "type": "sell", @@ -5099,9 +5099,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 3, + "trigger_count": 0, "success_rate": null, - "last_triggered": "2026-06-24T10:23:51.435819" + "last_triggered": null } ], "last_evaluated": "2026-06-24T10:23:51.435819" @@ -5197,9 +5197,9 @@ }, "priority": 1, "rationale": "价格回调到支撑区,弱势市场低吸", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" }, { "id": "300308_breakout_chase", @@ -5261,9 +5261,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 0, + "trigger_count": 1, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" } ], "initialized_at": "2026-06-24T10:23:51.435849" @@ -5401,9 +5401,9 @@ }, "priority": 1, "rationale": "价格回调到支撑区,弱势市场低吸", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" }, { "id": "300548_breakout_chase", @@ -5465,9 +5465,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 0, + "trigger_count": 1, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" } ], "initialized_at": "2026-06-24T10:23:51.438379" @@ -5591,9 +5591,9 @@ }, "priority": 1, "rationale": "价格回调到支撑区,弱势市场低吸", - "trigger_count": 0, + "trigger_count": 1, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" }, { "id": "300690_breakout_chase", @@ -5642,9 +5642,9 @@ }, "priority": 4, "rationale": "达到目标价,减半仓锁定利润", - "trigger_count": 0, + "trigger_count": 1, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" }, { "id": "300690_hold", @@ -5655,9 +5655,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" } ], "initialized_at": "2026-06-24T10:23:51.440911" @@ -5802,9 +5802,9 @@ }, "priority": 1, "rationale": "价格回调到支撑区,弱势市场低吸", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" }, { "id": "300750_breakout_chase", @@ -5853,9 +5853,9 @@ }, "priority": 4, "rationale": "达到目标价,减半仓锁定利润", - "trigger_count": 0, + "trigger_count": 1, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" }, { "id": "300750_hold", @@ -5866,9 +5866,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 0, + "trigger_count": 1, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" } ], "initialized_at": "2026-06-24T10:23:51.443454" @@ -5978,9 +5978,9 @@ }, "priority": 1, "rationale": "价格回调到支撑区,弱势市场低吸", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" }, { "id": "518880_breakout_chase", @@ -6029,9 +6029,9 @@ }, "priority": 4, "rationale": "达到目标价,减半仓锁定利润", - "trigger_count": 0, + "trigger_count": 1, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" }, { "id": "518880_hold", @@ -6042,9 +6042,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 0, + "trigger_count": 1, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" } ], "initialized_at": "2026-06-24T10:23:51.446049" @@ -6189,9 +6189,9 @@ }, "priority": 1, "rationale": "价格回调到支撑区,弱势市场低吸", - "trigger_count": 0, + "trigger_count": 1, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" }, { "id": "600036_breakout_chase", @@ -6253,9 +6253,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" } ], "initialized_at": "2026-06-24T10:23:51.448654" @@ -6351,9 +6351,9 @@ }, "priority": 1, "rationale": "价格回调到支撑区,弱势市场低吸", - "trigger_count": 3, + "trigger_count": 6, "success_rate": null, - "last_triggered": "2026-06-24T10:23:51.453703" + "last_triggered": "2026-06-24" }, { "id": "600519_breakout_chase", @@ -6415,9 +6415,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 3, + "trigger_count": 4, "success_rate": null, - "last_triggered": "2026-06-24T10:23:51.453703" + "last_triggered": "2026-06-24" } ], "last_evaluated": "2026-06-24T10:23:51.453703" @@ -6606,9 +6606,9 @@ }, "priority": 4, "rationale": "达到目标价,减半仓锁定利润", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" }, { "id": "600563_hold", @@ -6619,9 +6619,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 0, + "trigger_count": 1, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" } ], "initialized_at": "2026-06-24T10:23:51.453733" @@ -6759,9 +6759,9 @@ }, "priority": 1, "rationale": "价格回调到支撑区,弱势市场低吸", - "trigger_count": 0, + "trigger_count": 1, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" }, { "id": "600739_breakout_chase", @@ -6823,9 +6823,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" } ], "initialized_at": "2026-06-24T10:23:51.456350" @@ -6834,17 +6834,17 @@ { "code": "601318", "name": "中国平安", - "price": 49.73, + "price": 49.07, "cost": 0, "shares": 0, "avg_price": 0, - "action": "盈利持有 | 目标53.88 | 止损48.24 | 买入区48.74~50.5 | 信号:观望", - "stop_loss": 48.24, - "entry_low": 48.74, - "entry_high": 50.5, - "tech_snapshot": "形态:光头光脚阴线/bearish 量价:主动卖盘占优 强撑:46.34 弱撑:49.33 弱压:50.5 强压:53.88", + "action": "盈利持有 | 目标53.59 | 止损47.6 | 买入区48.09~50.0 | 信号:观望", + "stop_loss": 47.6, + "entry_low": 48.09, + "entry_high": 50.0, + "tech_snapshot": "形态:光头光脚阴线/bearish 量价:主动卖盘占优 强撑:45.74 弱撑:48.45 弱压:50.4 强压:53.59", "timing_signal": "观望", - "rr_ratio": 2.79, + "rr_ratio": 3.07, "status": "updated", "note": "", "timestamp": "2026-06-24 09:01", @@ -6856,7 +6856,7 @@ "position_advice": "减仓或观望", "time_horizon": "观望", "created_at": "2026-06-22 11:50", - "take_profit": 53.88, + "take_profit": 53.59, "changelog": [ { "date": "2026-06-22 12:01", @@ -6885,7 +6885,7 @@ { "id": "601318_stop_loss", "condition": { - "price": "<48.24" + "price": "<47.6" }, "action": { "type": "sell", @@ -6902,26 +6902,26 @@ "id": "601318_buy_dip", "condition": { "scenario": "weak_consolidation", - "price": "<=50.5", - "price_lower": ">=48.74" + "price": "<=50.0", + "price_lower": ">=48.09" }, "action": { "type": "buy", "amount": "normal", - "limit": 48.74, + "limit": 48.09, "reason": "回调支撑买入" }, "priority": 1, "rationale": "价格回调到支撑区,弱势市场低吸", - "trigger_count": 3, + "trigger_count": 2, "success_rate": null, - "last_triggered": "2026-06-24T10:23:51.461460" + "last_triggered": "2026-06-24" }, { "id": "601318_breakout_chase", "condition": { "scenario": "bullish_recovery", - "price": ">=53.88" + "price": ">=53.59" }, "action": { "type": "buy", @@ -6955,7 +6955,7 @@ { "id": "601318_take_profit", "condition": { - "price": ">=53.88" + "price": ">=53.59" }, "action": { "type": "sell", @@ -6977,9 +6977,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 3, + "trigger_count": 0, "success_rate": null, - "last_triggered": "2026-06-24T10:23:51.461460" + "last_triggered": null } ], "last_evaluated": "2026-06-24T10:23:51.461460" @@ -7117,9 +7117,9 @@ }, "priority": 1, "rationale": "价格回调到支撑区,弱势市场低吸", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" }, { "id": "601899_breakout_chase", @@ -7181,9 +7181,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 0, + "trigger_count": 1, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" } ], "initialized_at": "2026-06-24T10:23:51.461488" @@ -7358,9 +7358,9 @@ }, "priority": 4, "rationale": "达到目标价,减半仓锁定利润", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" }, { "id": "603259_hold", @@ -7371,9 +7371,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 0, + "trigger_count": 1, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" } ], "initialized_at": "2026-06-24T10:23:51.463984" @@ -7505,9 +7505,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" } ], "initialized_at": "2026-06-24T10:23:51.466468" @@ -7716,9 +7716,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" } ], "initialized_at": "2026-06-24T10:23:51.469011" @@ -7856,9 +7856,9 @@ }, "priority": 1, "rationale": "价格回调到支撑区,弱势市场低吸", - "trigger_count": 0, + "trigger_count": 1, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" }, { "id": "688639_breakout_chase", @@ -7920,9 +7920,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" } ], "initialized_at": "2026-06-24T10:23:51.471510" @@ -7931,17 +7931,17 @@ { "code": "688795", "name": "摩尔线程-U", - "price": 685.03, + "price": 684.0, "cost": 0, "shares": 0, "avg_price": 0, - "action": "盈利持有 | 目标818.99 | 止损664.48 | 买入区671.33~698.73 | 信号:观望", - "stop_loss": 664.48, - "entry_low": 671.33, - "entry_high": 698.73, - "tech_snapshot": "形态:锤子线/T字线/bullish 量价:主动卖盘占优 强撑:563.22 弱撑:669.69 弱压:704.03 强压:818.99", + "action": "盈利持有 | 目标818.65 | 止损663.48 | 买入区670.32~697.68 | 信号:观望", + "stop_loss": 663.48, + "entry_low": 670.32, + "entry_high": 697.68, + "tech_snapshot": "形态:锤子线/T字线/bullish 量价:主动卖盘占优 强撑:563.22 弱撑:669.0 弱压:704.03 强压:818.65", "timing_signal": "观望", - "rr_ratio": 6.52, + "rr_ratio": 6.56, "status": "updated", "note": "", "timestamp": "2026-06-24 09:01", @@ -7953,7 +7953,7 @@ "position_advice": "正常配置", "time_horizon": "数月~1年", "created_at": "2026-06-18 17:15", - "take_profit": 818.99, + "take_profit": 818.65, "updated_reason": "技术信号变化: 大盘中性,行业中性,高估值,放量下跌,等企稳再入: 止损683.91→660.96 | 形态:带上影阳线/neutral 量价:主动卖盘占优 强撑:568.43 弱撑:660.96 弱压:746.15 强压:", "changelog": [ { @@ -8032,7 +8032,7 @@ { "id": "688795_stop_loss", "condition": { - "price": "<664.48" + "price": "<663.48" }, "action": { "type": "sell", @@ -8049,26 +8049,26 @@ "id": "688795_buy_dip", "condition": { "scenario": "weak_consolidation", - "price": "<=698.73", - "price_lower": ">=671.33" + "price": "<=697.68", + "price_lower": ">=670.32" }, "action": { "type": "buy", "amount": "normal", - "limit": 671.33, + "limit": 670.32, "reason": "回调支撑买入" }, "priority": 1, "rationale": "价格回调到支撑区,弱势市场低吸", - "trigger_count": 3, + "trigger_count": 2, "success_rate": null, - "last_triggered": "2026-06-24T10:23:51.476631" + "last_triggered": "2026-06-24" }, { "id": "688795_breakout_chase", "condition": { "scenario": "bullish_recovery", - "price": ">=818.99" + "price": ">=818.65" }, "action": { "type": "buy", @@ -8102,7 +8102,7 @@ { "id": "688795_take_profit", "condition": { - "price": ">=818.99" + "price": ">=818.65" }, "action": { "type": "sell", @@ -8124,9 +8124,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 3, + "trigger_count": 0, "success_rate": null, - "last_triggered": "2026-06-24T10:23:51.476631" + "last_triggered": null } ], "last_evaluated": "2026-06-24T10:23:51.476631" @@ -8264,9 +8264,9 @@ }, "priority": 1, "rationale": "价格回调到支撑区,弱势市场低吸", - "trigger_count": 0, + "trigger_count": 1, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" }, { "id": "688802_breakout_chase", @@ -8328,9 +8328,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" } ], "initialized_at": "2026-06-24T10:23:51.476659" @@ -8518,9 +8518,9 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" } ], "initialized_at": "2026-06-24T10:23:51.479161" @@ -8653,14 +8653,14 @@ }, "priority": 99, "rationale": "没有分支匹配时的默认动作", - "trigger_count": 0, + "trigger_count": 3, "success_rate": null, - "last_triggered": null + "last_triggered": "2026-06-24" } ] } } ], - "total": 42, - "regenerated_at": "2026-06-24 10:01" + "total": 43, + "regenerated_at": "2026-06-24 10:31" } \ No newline at end of file diff --git a/data/portfolio.json b/data/portfolio.json index 0f52272..b02854b 100644 --- a/data/portfolio.json +++ b/data/portfolio.json @@ -26,8 +26,8 @@ "action_note": "⚠️盈亏比偏低(1:1.2),不建议加仓", "timing_signal": "大盘中性,行业偏弱,蓝筹,持有" }, - "price": 416.4, - "change_pct": 0.39 + "price": 416.6, + "change_pct": 0.68 }, { "code": "00981", @@ -55,8 +55,8 @@ "action_note": "⚠️盈亏比偏低(1:1.3),不建议加仓", "timing_signal": "大盘中性,行业中性,高估值,蓝筹,持有" }, - "price": 83.55, - "change_pct": 7.32 + "price": 83.9, + "change_pct": 7.77 }, { "code": "01088", @@ -84,8 +84,8 @@ "action_note": "⚠️盈亏比偏低(1:1.2),不建议加仓", "timing_signal": "大盘中性,行业中性,蓝筹,持有" }, - "price": 41.56, - "change_pct": -1.19 + "price": 41.54, + "change_pct": -1.28 }, { "code": "01211", @@ -113,8 +113,8 @@ "action_note": "深套持有", "timing_signal": "大盘中性,行业偏弱,蓝筹,持有" }, - "price": 74.9, - "change_pct": -1.25 + "price": 75.1, + "change_pct": -0.99 }, { "code": "01478", @@ -142,8 +142,8 @@ "action_note": "深套持有", "timing_signal": "大盘中性,行业中性,低估值,持有" }, - "price": 7.63, - "change_pct": -3.17 + "price": 7.67, + "change_pct": -2.79 }, { "code": "01888", @@ -171,7 +171,7 @@ "action_note": "短炒强趋势持", "timing_signal": "大盘中性,行业偏弱,高估值,强趋势持" }, - "price": 94.4, + "price": 94.8, "change_pct": 8.19 }, { @@ -258,8 +258,8 @@ "action_note": "深套持有", "timing_signal": "大盘中性,行业偏弱,蓝筹,持有" }, - "price": 97.7, - "change_pct": -1.26 + "price": 98.45, + "change_pct": -0.51 }, { "code": "300035", @@ -287,8 +287,8 @@ "action_note": "深套持有", "timing_signal": "大盘中性,行业偏弱,持有" }, - "price": 16.12, - "change_pct": -1.47 + "price": 16.06, + "change_pct": -1.83 }, { "code": "300548", @@ -316,8 +316,8 @@ "action_note": "短炒强趋势持", "timing_signal": "大盘中性,行业中性,高估值,强趋势持" }, - "price": 286.54, - "change_pct": 0.18 + "price": 283.8, + "change_pct": -0.78 }, { "code": "300690", @@ -345,8 +345,8 @@ "action_note": "⚠️盈亏比偏低(1:1.5),不建议加仓", "timing_signal": "大盘中性,行业偏弱,持有" }, - "price": 22.83, - "change_pct": -3.39 + "price": 22.79, + "change_pct": -3.55 }, { "code": "300750", @@ -374,8 +374,8 @@ "action_note": "", "timing_signal": "大盘中性,行业偏弱,蓝筹,持有" }, - "price": 394.29, - "change_pct": 0.45 + "price": 392.99, + "change_pct": 0.12 }, { "code": "518880", @@ -403,8 +403,8 @@ "action_note": "深套持有", "timing_signal": "大盘中性,行业偏弱,持有" }, - "price": 8.47, - "change_pct": -0.81 + "price": 8.46, + "change_pct": -0.98 }, { "code": "600036", @@ -432,8 +432,8 @@ "action_note": "⚠️盈亏比偏低(1:1.2),不建议加仓", "timing_signal": "大盘中性,行业偏强,低估值,蓝筹,弱势持有" }, - "price": 36.97, - "change_pct": -1.15 + "price": 37.04, + "change_pct": -0.96 }, { "code": "600563", @@ -490,8 +490,8 @@ "action_note": "⚠️盈亏比偏低(1:1.2),不建议加仓", "timing_signal": "大盘中性,行业偏强,持有" }, - "price": 10.48, - "change_pct": -1.6 + "price": 10.47, + "change_pct": -1.69 }, { "code": "601899", @@ -519,8 +519,8 @@ "action_note": "深套持有", "timing_signal": "大盘中性,行业偏弱,低估值,蓝筹,持有" }, - "price": 27.58, - "change_pct": -0.79 + "price": 27.51, + "change_pct": -0.94 }, { "code": "603259", @@ -548,8 +548,8 @@ "action_note": "", "timing_signal": "大盘中性,行业偏强,低估值,持有" }, - "price": 115.01, - "change_pct": 8.18 + "price": 116.45, + "change_pct": 9.54 }, { "code": "688411", @@ -577,8 +577,8 @@ "action_note": "", "timing_signal": "持有" }, - "price": 266.48, - "change_pct": -2.12 + "price": 266.91, + "change_pct": -1.96 }, { "code": "688981", @@ -606,8 +606,8 @@ "action_note": "", "timing_signal": "大盘中性,行业中性,高估值,蓝筹,持有" }, - "price": 151.99, - "change_pct": 7.26 + "price": 151.13, + "change_pct": 6.65 } ] } \ No newline at end of file diff --git a/data/price_history.json b/data/price_history.json index 42029e8..dc9c81f 100644 --- a/data/price_history.json +++ b/data/price_history.json @@ -107,8 +107,8 @@ { "date": "2026-06-24", "high": 88.32, - "low": 83.23, - "close": 83.23 + "low": 83.0, + "close": 83.02 } ], "00700": [ @@ -1284,7 +1284,7 @@ "date": "2026-06-24", "high": 68.8, "low": 65.92, - "close": 66.98 + "close": 67.09 } ], "300548": [ @@ -2316,7 +2316,7 @@ "date": "2026-06-24", "high": 745.2, "low": 660.01, - "close": 685.03 + "close": 684.0 } ], "688802": [ @@ -2609,8 +2609,8 @@ { "date": "2026-06-24", "high": 52.43, - "low": 49.71, - "close": 49.73 + "low": 49.05, + "close": 49.07 } ], "002171": [ diff --git a/scripts/branch_scanner.py b/scripts/branch_scanner.py index 414ccfe..6bacac3 100644 --- a/scripts/branch_scanner.py +++ b/scripts/branch_scanner.py @@ -61,7 +61,7 @@ def save_decisions(data): def check_condition(branch, scenario_id, price): - """检查分支条件是否满足""" + """检查分支条件是否满足 — 同步 strategy_tree._check_branch_condition 逻辑""" cond = branch.get("condition", {}) required_scenario = cond.get("scenario", "") if required_scenario and required_scenario != scenario_id: @@ -76,6 +76,18 @@ def check_condition(branch, scenario_id, price): if op == ">" and not (price > val): return False if op == "<=" and not (price <= val): return False if op == ">=" and not (price >= val): return False + + # 买入区下界(price_lower)检查 — 之前遗漏 + price_lower = cond.get("price_lower", "") + if price_lower and price: + ops = re.findall(r"([<>=!]+)\s*([\d.]+)", price_lower) + for op, val_str in ops: + val = float(val_str) + if op == "<" and not (price < val): return False + if op == ">" and not (price > val): return False + if op == "<=" and not (price <= val): return False + if op == ">=" and not (price >= val): return False + return True @@ -114,11 +126,17 @@ def main(): if not price: continue - for br in branches: + # 找出所有适用的分支,选最优(优先级数字最低) + best = None + for br in sorted(branches, key=lambda b: b.get("priority", 999)): if check_condition(br, sid, price): - br["trigger_count"] = br.get("trigger_count", 0) + 1 - br["last_triggered"] = today - triggered.append((code, entry.get("name", ""), br)) + best = br + break + + if best: + best["trigger_count"] = best.get("trigger_count", 0) + 1 + best["last_triggered"] = today + triggered.append((code, entry.get("name", ""), best)) if triggered: save_decisions(data)