Commit Graph

354 Commits

Author SHA1 Message Date
Youssef Aitousarrah 8ba5b8fd7e docs(iteration-system): collapse strategies/ into scanners/
Scanners and strategies are 1:1 in the current codebase — separate folder
was artificial. Each scanner file now captures both implementation and thesis.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 07:35:40 -07:00
github-actions[bot] a40decb60c chore: update performance tracking 2026-04-08 2026-04-08 14:14:12 +00:00
github-actions[bot] 716c353c15 chore: daily discovery 2026-04-08 2026-04-08 14:13:54 +00:00
Youssef Aitousarrah 05168c7a96 docs(iteration-system): add GitHub Actions automation layer
Adds daily /iterate and weekly /research-strategy cron workflows to the
spec — full autonomous loop with PR-gated merges, no auto-merge to main.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 20:34:21 -07:00
Youssef Aitousarrah 91279fe60b docs: add iteration system design spec
Defines /iterate and /research-strategy skills + docs/iterations/ folder
structure for a generic learn-improve-repeat cycle, demonstrated with the
trading agent discovery pipeline.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 20:24:12 -07:00
github-actions[bot] e942ee4b9f chore: update performance tracking 2026-04-07 2026-04-07 23:46:04 +00:00
github-actions[bot] fa33f54869 chore: daily discovery 2026-04-07 2026-04-07 23:45:31 +00:00
Youssef Aitousarrah c09cc7ec25 fix(y_finance): make suppress_yfinance_warnings thread-safe
The previous implementation redirected sys.stderr to /dev/null using a
context manager. This is not thread-safe: 8 concurrent scanner threads each
mutate sys.stderr, and when one thread's context manager closes the devnull
file, another thread that captured devnull as its saved stderr attempts to
write to the closed fd and raises "I/O operation on closed file".

This corrupted sys.stderr state caused _fetch_batch_prices to fail and
all per-ticker get_stock_price fallback calls to return None, resulting in
every candidate being dropped with "no data available".

Fix by suppressing at the Python logging level instead of redirecting
sys.stderr. Logger.setLevel() is protected by internal locks and is safe
to call from concurrent threads.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 16:37:03 -07:00
github-actions[bot] 3a69427dc8 chore: update performance tracking 2026-04-07 2026-04-07 23:29:44 +00:00
github-actions[bot] 42e7730257 chore: daily discovery 2026-04-07 2026-04-07 23:29:40 +00:00
Youssef Aitousarrah 704af1a855 fix(discovery): commit risk_metrics.py and reduce Minervini max_tickers to 50
Two bugs causing zero recommendations:

1. risk_metrics.py was untracked — importing it raised ModuleNotFoundError which
   was caught by the outer try/except in filter.py, silently dropping all 32
   candidates that reached the fundamental risk check stage.

2. Minervini scanner at max_tickers=200 took >5 min to download 200 tickers x 1y
   of OHLCV data. ThreadPoolExecutor.cancel() cannot kill a running thread, so the
   download kept running as a zombie thread for 20 more minutes after the pipeline
   completed, holding the Python process alive until the 30-min workflow timeout
   killed the entire job.

   Reducing to 50 tickers brings the download to ~75s, well under the 300s global
   scanner timeout.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 16:24:29 -07:00
github-actions[bot] 2da07c6797 chore: update performance tracking 2026-04-07 2026-04-07 23:21:27 +00:00
github-actions[bot] b93e4606ea chore: daily discovery 2026-04-07 2026-04-07 23:21:13 +00:00
Youssef Aitousarrah 2e79c2245f fix(filter): only filter upside intraday movers, not downside
The same-day mover filter used abs() to check intraday movement, which
filtered both gap-ups AND gap-downs. On volatile/crash days (e.g. 2026-04-07)
all stocks dropped >10% from open, causing every candidate to be filtered and
leaving zero recommendations.

The filter's purpose is to avoid chasing stocks that already ran up. A stock
down 20% intraday is not "stale" — it should be evaluated on its merits.
Changed threshold check from abs(pct) >= threshold to pct >= threshold so only
upside movers are filtered.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 12:51:41 -07:00
github-actions[bot] c28596c505 chore: update performance tracking 2026-04-07 2026-04-07 14:35:44 +00:00
github-actions[bot] 32fa765cbc chore: daily discovery 2026-04-07 2026-04-07 14:35:21 +00:00
github-actions[bot] 55ac222e30 chore: update performance tracking 2026-04-06 2026-04-06 21:29:29 +00:00
github-actions[bot] 74c4671c74 chore: daily discovery 2026-04-06 2026-04-06 21:29:22 +00:00
Youssef Aitousarrah 957b009da1 fix(minervini): cap ticker universe to prevent CI timeout
yf.download(592 tickers, period=1y) takes 20+ minutes in CI, causing
the 30-minute job timeout to trigger. Add max_tickers=200 (configurable)
to limit the batch download to the first N tickers from the file. The
concurrent scanner pool already has a 5-min global timeout, but the hung
download thread monopolises network connections and starves the filter stage.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 14:24:22 -07:00
github-actions[bot] 1f92269fcb chore: update performance tracking 2026-04-06 2026-04-06 21:22:28 +00:00
github-actions[bot] 4935baa34c chore: daily discovery 2026-04-06 2026-04-06 21:22:12 +00:00
Youssef Aitousarrah b68a43ec0d feat(scanners): add minervini scanner to registry
minervini.py existed but was never committed. Without the file on the
remote, the __init__.py import added in the previous fix causes an
ImportError in CI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 13:51:42 -07:00
github-actions[bot] 8706484c16 chore: update performance tracking 2026-04-06 2026-04-06 20:50:00 +00:00
Youssef Aitousarrah 32d89c3bfc fix(ci): restore daily discovery workflow
- Add permissions: contents: write so git push works (was failing with 403)
- Add continue-on-error: true on discovery step so partial output still commits
- Change all commit/tracking/position steps to if: always() so they run regardless of discovery outcome
- Use commit-then-pull-rebase-then-push pattern to handle branch divergence
- Fix minervini scanner missing from scanners/__init__.py (enabled in config but never loaded)
- Fix .gitignore: results/* + !results/discovery/ so CI run logs can be committed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 13:46:21 -07:00
Youssef Aitousarrah 719a2d3f4e fix(scanners): rank by signal quality before limiting in 3 more scanners
Same issue as options_flow: early exit on candidate count discards strong
signals that happen to be later in iteration order.

insider_buying: Dict iteration order matched OpenInsider HTML scrape order,
not signal quality. Now scores by cluster buys + C-suite + dollar value,
then takes top N.

technical_breakout: Stopped at limit*2 in file order despite data already
being batch-downloaded (zero API cost to check all). Removed early exit,
scan full universe, sort by volume_multiple.

sector_rotation: Checked laggards in arbitrary dict order, spending API
calls on random tickers. Now sorts by most-negative 5d return first so
the strongest laggard candidates are checked before hitting the budget.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 13:46:21 -07:00
Youssef Aitousarrah 136fa47645 fix(options_flow): scan full universe before applying limit, rank by signal strength
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 <noreply@anthropic.com>
2026-04-06 13:46:21 -07:00
Youssef Aitousarrah 61b731ac28 fix(filter): replace tqdm with logger in batch news functions to fix I/O error
tqdm writes to stderr immediately on __enter__, before any loop iteration.
In Streamlit's thread/subprocess context stderr can be a closed pipe, causing
'I/O operation on closed file' which _run_call catches and returns {} — so
the entire news enrichment step was silently skipped every run.

Replaced tqdm progress bars with logger.info() calls in:
- get_batch_stock_news_google() in openai.py
- get_batch_stock_news_openai() in openai.py
- Reddit DD parallel evaluation in reddit_api.py

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 13:46:21 -07:00
github-actions[bot] 21b33c6709 chore: update performance tracking 2026-04-06 2026-04-06 13:57:37 +00:00
github-actions[bot] 76b91fbccb chore: daily discovery 2026-04-06 2026-04-06 13:57:19 +00:00
github-actions[bot] 5749c8e33e chore: update performance tracking 2026-04-05 2026-04-05 13:39:10 +00:00
github-actions[bot] 7b2b4f7052 chore: daily discovery 2026-04-05 2026-04-05 13:38:54 +00:00
github-actions[bot] 42999857af chore: update performance tracking 2026-04-04 2026-04-04 13:37:06 +00:00
github-actions[bot] 1e06895946 chore: daily discovery 2026-04-04 2026-04-04 13:36:51 +00:00
github-actions[bot] a8ccb0e396 chore: update performance tracking 2026-04-03 2026-04-03 13:46:52 +00:00
github-actions[bot] d5cebd9dff chore: daily discovery 2026-04-03 2026-04-03 13:46:37 +00:00
github-actions[bot] fba5b91242 chore: update performance tracking 2026-04-02 2026-04-02 14:04:43 +00:00
github-actions[bot] a82199be5c chore: daily discovery 2026-04-02 2026-04-02 14:04:29 +00:00
github-actions[bot] 9edee768e9 chore: update performance tracking 2026-04-01 2026-04-01 14:13:16 +00:00
github-actions[bot] 28c5392fa3 chore: daily discovery 2026-04-01 2026-04-01 14:13:10 +00:00
github-actions[bot] f9ad043be0 chore: update performance tracking 2026-03-31 2026-03-31 14:10:53 +00:00
github-actions[bot] 23d1f3db99 chore: daily discovery 2026-03-31 2026-03-31 14:10:48 +00:00
github-actions[bot] d764cee16d chore: update performance tracking 2026-03-30 2026-03-30 14:08:52 +00:00
github-actions[bot] 33ab46f302 chore: daily discovery 2026-03-30 2026-03-30 14:08:46 +00:00
github-actions[bot] e737204ef8 chore: update performance tracking 2026-03-29 2026-03-29 13:37:26 +00:00
github-actions[bot] 3e02014c6c chore: daily discovery 2026-03-29 2026-03-29 13:37:08 +00:00
github-actions[bot] 85a5cf9e46 chore: update performance tracking 2026-03-28 2026-03-28 13:35:54 +00:00
github-actions[bot] 2f794608b1 chore: daily discovery 2026-03-28 2026-03-28 13:35:35 +00:00
github-actions[bot] 01019b3533 chore: update performance tracking 2026-03-27 2026-03-27 13:51:12 +00:00
github-actions[bot] e662a1f4dc chore: daily discovery 2026-03-27 2026-03-27 13:51:04 +00:00
github-actions[bot] 6328458f90 chore: update performance tracking 2026-03-26 2026-03-26 14:07:03 +00:00