diff options
| author | TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com> | 2026-04-02 10:13:10 +0900 |
|---|---|---|
| committer | TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com> | 2026-04-02 10:13:10 +0900 |
| commit | e9c791ae2b14884f8f0525da5fcaa1710ca1fc63 (patch) | |
| tree | 752c219a95abe7bdbfbf0644711f7dede407aa7b /scripts/stock_screener.py | |
| parent | 35120795147adf53de59b7f2a3c8aa14adec9a56 (diff) | |
refactor: complete US stock migration
- Data collector: Alpaca REST polling (replaces Binance WebSocket)
- Order executor: Alpaca submit_order (replaces ccxt)
- Claude stock screener: daily MOC candidate analysis
- Remove ccxt/websockets dependencies
- Default universe: AAPL, MSFT, GOOGL, AMZN, TSLA + 28 more
- 399 tests passing, lint clean
Diffstat (limited to 'scripts/stock_screener.py')
| -rwxr-xr-x | scripts/stock_screener.py | 72 |
1 files changed, 52 insertions, 20 deletions
diff --git a/scripts/stock_screener.py b/scripts/stock_screener.py index 387bfea..7a5c0ba 100755 --- a/scripts/stock_screener.py +++ b/scripts/stock_screener.py @@ -10,6 +10,7 @@ Usage: Requires: ANTHROPIC_API_KEY environment variable """ + import argparse import asyncio import json @@ -51,15 +52,17 @@ async def get_market_data(alpaca: AlpacaClient, symbols: list[str]) -> list[dict lows = [float(b["l"]) for b in bars] range_pct = (max(highs) - min(lows)) / close * 100 if close > 0 else 0 - results.append({ - "symbol": symbol, - "close": close, - "change_pct": round(change_pct, 2), - "volume": volume, - "vol_ratio": round(vol_ratio, 2), - "range_5d_pct": round(range_pct, 2), - "is_bullish": close > float(latest["o"]), # Today bullish? - }) + results.append( + { + "symbol": symbol, + "close": close, + "change_pct": round(change_pct, 2), + "volume": volume, + "vol_ratio": round(vol_ratio, 2), + "range_5d_pct": round(range_pct, 2), + "is_bullish": close > float(latest["o"]), # Today bullish? + } + ) except Exception as exc: print(f" Warning: Failed to fetch {symbol}: {exc}") @@ -137,19 +140,45 @@ async def analyze_with_claude(prompt: str, api_key: str) -> list[dict]: # Default universe of liquid US stocks DEFAULT_UNIVERSE = [ # Tech - "AAPL", "MSFT", "GOOGL", "AMZN", "META", "NVDA", "TSLA", "AMD", "INTC", "CRM", + "AAPL", + "MSFT", + "GOOGL", + "AMZN", + "META", + "NVDA", + "TSLA", + "AMD", + "INTC", + "CRM", # Finance - "JPM", "BAC", "GS", "MS", "V", "MA", + "JPM", + "BAC", + "GS", + "MS", + "V", + "MA", # Healthcare - "JNJ", "UNH", "PFE", "ABBV", + "JNJ", + "UNH", + "PFE", + "ABBV", # Consumer - "WMT", "KO", "PEP", "MCD", "NKE", + "WMT", + "KO", + "PEP", + "MCD", + "NKE", # Energy - "XOM", "CVX", + "XOM", + "CVX", # Industrial - "CAT", "BA", "GE", + "CAT", + "BA", + "GE", # ETFs - "SPY", "QQQ", "IWM", + "SPY", + "QQQ", + "IWM", ] @@ -187,8 +216,7 @@ async def main_async(top_n: int = 5, universe: list[str] | None = None): # Pre-filter obvious rejects candidates = [ - s for s in market_data - if s["is_bullish"] and s["vol_ratio"] >= 0.8 and s["change_pct"] > -2 + s for s in market_data if s["is_bullish"] and s["vol_ratio"] >= 0.8 and s["change_pct"] > -2 ] print(f"Pre-filter: {len(candidates)} candidates (bullish, decent volume)\n") @@ -211,7 +239,9 @@ async def main_async(top_n: int = 5, universe: list[str] | None = None): # Find market data for this symbol md = next((m for m in market_data if m["symbol"] == rec["symbol"]), None) if md: - print(f" Close: ${md['close']:.2f} | Change: {md['change_pct']:+.2f}% | Vol Ratio: {md['vol_ratio']:.1f}x") + print( + f" Close: ${md['close']:.2f} | Change: {md['change_pct']:+.2f}% | Vol Ratio: {md['vol_ratio']:.1f}x" + ) else: print("Claude found no qualifying stocks today.") else: @@ -237,7 +267,9 @@ async def main_async(top_n: int = 5, universe: list[str] | None = None): print("-" * 60) for i, (s, score) in enumerate(scored[:top_n], 1): print(f"#{i} {s['symbol']} (Score: {score})") - print(f" Close: ${s['close']:.2f} | Change: {s['change_pct']:+.2f}% | Vol: {s['vol_ratio']:.1f}x") + print( + f" Close: ${s['close']:.2f} | Change: {s['change_pct']:+.2f}% | Vol: {s['vol_ratio']:.1f}x" + ) print("\n" + "=" * 60) |
