Drop over-progressed setups via live R:R; refresh trades on fetch
Answers "why does a too-far-progressed setup still show": setups are only recalculated by the scheduled R:R scan and manual fetch; at creation entry == current price (0% progress), so over-progression is a between-scans drift effect and must be judged at read time. - /trades now attaches current_price (latest close per ticker). - Qualification drops setups whose R:R recomputed from the current price falls below min_rr — i.e. price already ran toward target (reward consumed) or through the stop. Reuses the existing min_rr threshold instead of a separate progress %; far cleaner (a 3:1 is already ~1:1 by 33% progress). Skipped for historical setups (no current_price). - Fix: useFetchSymbolData now invalidates the trades queries, so a fetch/ recompute actually refreshes confidence/setups in the UI (was the cause of the stale 100% confidence lingering after recompute). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,24 @@ def best_target_probability(setup: Any) -> float:
|
||||
return max(probs, default=0.0)
|
||||
|
||||
|
||||
def live_risk_reward(setup: Any, current_price: float) -> float | None:
|
||||
"""R:R recomputed from the CURRENT price, not the (possibly stale) entry.
|
||||
|
||||
Returns None / a low value when the setup is no longer actionable: price
|
||||
already at/past the target (no reward left) or through the stop. This is how
|
||||
over-progressed setups get filtered without a separate 'max progress' knob.
|
||||
"""
|
||||
if setup.direction == "long":
|
||||
reward = setup.target - current_price
|
||||
risk = current_price - setup.stop_loss
|
||||
else:
|
||||
reward = current_price - setup.target
|
||||
risk = setup.stop_loss - current_price
|
||||
if reward <= 0 or risk <= 0:
|
||||
return 0.0
|
||||
return reward / risk
|
||||
|
||||
|
||||
def setup_qualifies(setup: Any, config: dict) -> bool:
|
||||
"""Whether a setup clears the activation gate.
|
||||
|
||||
@@ -28,6 +46,14 @@ def setup_qualifies(setup: Any, config: dict) -> bool:
|
||||
"""
|
||||
if setup.rr_ratio < config["min_rr"]:
|
||||
return False
|
||||
# Live R:R from the current price: drops setups whose price has already run
|
||||
# toward the target (reward consumed) or through the stop. Only applied when
|
||||
# a current price is attached (live list); skipped for historical setups.
|
||||
current_price = getattr(setup, "current_price", None)
|
||||
if current_price is not None:
|
||||
live_rr = live_risk_reward(setup, float(current_price))
|
||||
if live_rr is not None and live_rr < config["min_rr"]:
|
||||
return False
|
||||
if (setup.confidence_score or 0.0) < config["min_confidence"]:
|
||||
return False
|
||||
if config.get("require_high_conviction"):
|
||||
|
||||
Reference in New Issue
Block a user