branch_scanner: 修price_lower遗漏+只输最优分支

1. check_condition 新增 price_lower 检查(买入区下界)
   之前 buy_dip 分支的 price_lower: >=entry_low 从未被验证
   导致跌出买入区的股票也错误触发买入信号

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