From 136fa476458705bcd02e3cdf077173f6cc03d649 Mon Sep 17 00:00:00 2001 From: Youssef Aitousarrah Date: Sat, 21 Feb 2026 14:08:19 -0800 Subject: [PATCH] fix(options_flow): scan full universe before applying limit, rank by signal strength MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously the scanner stopped as soon as self.limit candidates were found from as_completed() futures. Since futures complete in non-deterministic network-latency order, this was equivalent to random sampling — fast-to- respond tickers won regardless of how strong their options signal was. Fix: collect all candidates from the full universe, then sort by options_score (unusual strike count weighted 1.5x for calls to favor bullish flow) before applying the limit. The top-N strongest signals are now always returned. Co-Authored-By: Claude Sonnet 4.6 --- .../dataflows/discovery/scanners/options_flow.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tradingagents/dataflows/discovery/scanners/options_flow.py b/tradingagents/dataflows/discovery/scanners/options_flow.py index 6db4ffb7..850789fe 100644 --- a/tradingagents/dataflows/discovery/scanners/options_flow.py +++ b/tradingagents/dataflows/discovery/scanners/options_flow.py @@ -85,14 +85,13 @@ class OptionsFlowScanner(BaseScanner): result = future.result() if result: candidates.append(result) - if len(candidates) >= self.limit: - # Cancel remaining futures - for f in futures: - f.cancel() - break except Exception: continue + # Sort by signal quality: unusual strike count, then bullish bias + candidates.sort(key=lambda c: c.get("options_score", 0), reverse=True) + candidates = candidates[: self.limit] + logger.info(f"Found {len(candidates)} unusual options flows") return candidates @@ -193,6 +192,10 @@ class OptionsFlowScanner(BaseScanner): f"{total_unusual_calls} unusual calls / {total_unusual_puts} unusual puts" ) + # Scoring: unusual strike count + bullish call bias bonus + # Calls weighted 1.5x to favour bullish directional flow + options_score = total_unusual_puts + (total_unusual_calls * 1.5) + return { "ticker": ticker, "source": self.name, @@ -203,6 +206,7 @@ class OptionsFlowScanner(BaseScanner): "unusual_calls": total_unusual_calls, "unusual_puts": total_unusual_puts, "best_expiration": best_expiration, + "options_score": options_score, } except Exception as e: