Playwright X scraper, daily notes, feed analysis

This commit is contained in:
2026-02-09 17:26:02 -06:00
parent be0315894e
commit 6592590dac
10 changed files with 37672 additions and 252 deletions

View File

@ -1,62 +1,66 @@
# 2026-02-09
# 2026-02-09 — Monday
## Market Watch Launch Day
- GARP paper trading simulator went live
- 9 AM systemd timer fired but crashed (scanner returns list, code expected dict) — fixed
- Manual run at 10:49 AM — **7 positions opened**:
- DUOL (57 shares @ $116.35)
- ALLY (156 shares @ $42.65)
- JHG (138 shares @ $48.21)
- INCY (61 shares @ $108.69)
- PINS (332 shares @ $20.06)
- EXEL (152 shares @ $43.80)
- CART (187 shares @ $35.49)
- ~$46.5K deployed, ~$53.5K cash remaining
- Portal live at marketwatch.local:8889
- Multiplayer game engine working — "GARP Challenge" game created
## X Feed Analysis Day
Major session analyzing Polymarket/crypto tweets D J forwarded from X feed.
## Super Bowl Results (from last night)
- Seahawks 36, Patriots 13
- kch123 copy-trade sim: ALL 5 positions won, +$728 on $1K bankroll (+72.8%)
- kch123 himself probably cleared ~$2M profit on this game
- Two weeks straight of wins for kch123 (60-0 last week + Super Bowl sweep)
### Tweets Investigated
1. **@browomo weather edge** — Pilot METAR data for Polymarket weather bets
- Wallet `0x594edB9112f...`: Claimed +$27K, actual **-$13,103** (387 losses, 51 wins)
- Verdict: SCAM/engagement bait
## Craigslist Account (from yesterday)
- Registered: case-lgn@protonmail.com, Nashville area
- Password set, credentials saved to .credentials/craigslist.env
- User ID: 405642144
- D J not ready for listings yet (needs photos)
2. **@ArchiveExplorer planktonXD** — "Buy everything under 5 cents"
- Wallet `0x4ffe49ba2a4c...`: Claimed +$104K, actual **-$9,517** (3090 losses, 1368 wins, 37% win rate)
- Verdict: SCAM/engagement bait
## D J Interests
- Looking at queen Murphy beds on Craigslist
- Wants to get rid of an old mattress (options discussed: Metro Nashville bulky pickup, free CL listing, dump)
- Interested in Olympics men's hockey (USA in Group C, games start Feb 11)
- Expanding analysis beyond Polymarket into crypto and stocks
- Goal: find market gaps to offset AI service costs ($200/mo Claude + infra)
- Getting crypto signals on Telegram, wants to forward them for analysis
- Asked about Tiiny AI (kickstarter AI hardware, 80GB unified memory, NPU) as potential Claude replacement
3. **@krajekis BTC 15-min LONG** — "+700% monthly, 1 trade/day at 9AM"
- Backtested 25 days: 52% win rate (coin flip), strategy loses 76% of capital
- Verdict: FABRICATED results
## Stock Screener Built
- GARP filters automated via yfinance (free, no API key)
- S&P 500 + S&P 400 MidCap scan (~902 tickers)
- Initial S&P 500 scan found 4: BAC, CFG, FITB, INCY
- Expanded scan found 22 total candidates
- Top non-bank picks: PINS, FSLR, PGR, NEM, ALLY
- Deep dive sub-agent ran on all 4 original picks
4. **@noisyb0y1 15-min arb** — "$99K in a day"
- Wallet `0xE594336603F4...`: Real strategy (buying both sides), actual PnL ~$9K not $99K
- Combined costs $0.70-$0.95 on some markets = genuine arb edge
- Verdict: INFLATED numbers, but strategy has merit → bookmarked for scanner
## X Post Analysis: @Shelpid_WI3M / anoin123
- Wallet 0x96489abc... is real, +$1.59M PnL, 216 trades
- BUT: concentrated single-thesis bet (NO on Iran strikes), not diversified alpha
- Post is a shill for PolyCopyBot (Telegram copy-trading bot)
- Verdict: real wallet, misleading narrative, exists to sell bot subscriptions
5. **5 more wallets** — spawned sub-agent to research @IH2P, Super Bowl trader, NegRisk arb, Elon insider, $270→$244K bot
## Tiiny AI Analysis
- 80GB LPDDR5X, ARM + NPU (160 TOPS), 18-40 tok/s, 30W
- Kickstarter vaporware — doesn't exist yet
- Would blow away D J's current 22GB VRAM setup IF it ships
- Recommended waiting for real reviews, not pre-ordering
### Pattern Identified
- Fintwit Polymarket accounts follow identical template: big $ claim → wallet → product shill
- Products being shilled: Clawdbots, Moltbook, Bullpen (affiliate/paid promos)
- Real money is in selling engagement, not trading
- Wallets are cherry-picked; PnL claims conflate position value with profit
## Lessons
- Scanner run_scan() returns list, not dict — caused systemd crash on first real run
- Always test the full pipeline end-to-end before relying on timers
- yfinance is reliable and free for fundamental data, no API key needed
### Built Today
- **Crypto signals pipeline** (`projects/crypto-signals/`)
- Signal parser for Telegram JSON exports
- Price fetcher (Binance US API)
- Backtester with Polymarket fee awareness
- Ready for D J's Telegram group export
- **Polymarket 15-min arb scanner** — systemd timer every 2 min
- Scans active Up or Down markets
- Checks orderbooks for combined < $1.00
- Paper trades and Telegram alerts
- Finding: markets are tight at steady state, arb windows likely during volatility
- **Playwright installed** — replaced flaky CDP websocket approach
- `connect_over_cdp('http://localhost:9222')` works with existing Chrome session
- X feed scraper working via Playwright
- **PowerInfer multi-GPU cron** — weekly Monday check for feature support
### Day-of-Week Stock Strategy
- D J's friend suggested buy Friday/Monday, sell midweek
- Backtested 5 years of SPY: Monday is strongest day (+0.114%, 62% win rate)
- Buy Mon Open → Sell Wed Close: 56% win rate, +0.265% avg, $10K→$17.8K
- But buy & hold still wins: $10K→$19K
- Verdict: weak edge, needs additional filters to be useful
### Infrastructure
- Polymarket fee structure documented: 15-min markets have taker fees, max 1.56% at 50/50
- Fee formula: `shares × price × 0.25 × (price × (1-price))²`
- Binance international is geo-blocked; Binance US works
### Pending
- D J sending Telegram crypto signal group export (Option 2: JSON export)
- Signal provider uses VWAP-based strategy
- Sub-agent researching 5 more wallets

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
{
"last_check": "2026-02-09T20:27:59.790122+00:00",
"last_check": "2026-02-09T23:25:59.773254+00:00",
"total_tracked": 3100,
"new_this_check": 0
}

View File

@ -0,0 +1,155 @@
[
{
"name": "guest_id_marketing",
"value": "v1%3A177052493168164632",
"domain": ".x.com",
"path": "/",
"secure": true,
"httpOnly": false,
"sameSite": "None"
},
{
"name": "guest_id_ads",
"value": "v1%3A177052493168164632",
"domain": ".x.com",
"path": "/",
"secure": true,
"httpOnly": false,
"sameSite": "None"
},
{
"name": "guest_id",
"value": "v1%3A177052493168164632",
"domain": ".x.com",
"path": "/",
"secure": true,
"httpOnly": false,
"sameSite": "None"
},
{
"name": "personalization_id",
"value": "\"v1_6O8SSA4FCcIXzFzq4cql3A==\"",
"domain": ".x.com",
"path": "/",
"secure": true,
"httpOnly": false,
"sameSite": "None"
},
{
"name": "__cuid",
"value": "7ec0f8364ef9466bb4d5e5398de60a7a",
"domain": ".x.com",
"path": "/",
"secure": false,
"httpOnly": false,
"sameSite": "Lax"
},
{
"name": "guest_id_marketing",
"value": "v1%3A177052493360013497",
"domain": ".twitter.com",
"path": "/",
"secure": true,
"httpOnly": false,
"sameSite": "None"
},
{
"name": "guest_id_ads",
"value": "v1%3A177052493360013497",
"domain": ".twitter.com",
"path": "/",
"secure": true,
"httpOnly": false,
"sameSite": "None"
},
{
"name": "personalization_id",
"value": "\"v1_0RdWTpuTILka/W8MwiVsGQ==\"",
"domain": ".twitter.com",
"path": "/",
"secure": true,
"httpOnly": false,
"sameSite": "None"
},
{
"name": "guest_id",
"value": "v1%3A177052493360013497",
"domain": ".twitter.com",
"path": "/",
"secure": true,
"httpOnly": false,
"sameSite": "None"
},
{
"name": "g_state",
"value": "{\"i_l\":0,\"i_ll\":1770524933853,\"i_b\":\"/335bZxZT54Tkc2wThT5DEH5v8hDZyhbe/JOl6uvF+k\",\"i_e\":{\"enable_itp_optimization\":0}}",
"domain": "x.com",
"path": "/",
"secure": false,
"httpOnly": false,
"sameSite": "Lax"
},
{
"name": "kdt",
"value": "Y9jfWROysXsnZyHwlffVbs8jvBJabIN4RGlZYFHP",
"domain": ".x.com",
"path": "/",
"secure": true,
"httpOnly": true,
"sameSite": "Lax"
},
{
"name": "auth_token",
"value": "219b71a535b96ef9f978612a48cf81a462643ee3",
"domain": ".x.com",
"path": "/",
"secure": true,
"httpOnly": true,
"sameSite": "None"
},
{
"name": "ct0",
"value": "e2c61ad6ce7115f2d8acd2062dc5c9a377140d9b570f871d9b25847f2d7a36fe512a424a359775d73a11a5a0a5154b6623b0021992a2b7f1e094d5ac5ee65cfeaf8ac87de09b7dcfc48f28a5b6dd15dc",
"domain": ".x.com",
"path": "/",
"secure": true,
"httpOnly": false,
"sameSite": "Lax"
},
{
"name": "twid",
"value": "u%3D741482516",
"domain": ".x.com",
"path": "/",
"secure": true,
"httpOnly": false,
"sameSite": "None"
},
{
"name": "lang",
"value": "en",
"domain": "x.com",
"path": "/",
"secure": false,
"httpOnly": false,
"sameSite": "Lax"
},
{
"name": "external_referer",
"value": "vC8TI7P7q9UHtLBqrmGBr3bhFoPD7nVN|0|8e8t2xd8A2w%3D",
"domain": ".x.com",
"path": "/",
"secure": true,
"httpOnly": false,
"sameSite": "Lax"
},
{
"name": "__cf_bm",
"value": "UjX5M.SqXScrW4zZ_GhiubhCXhv.8SI8uU7MkZCGT24-1770678794.1374662-1.0.1.1-4x.1srI8Lir7aTkBYJxMGMZQ2E3.EZKgF5S_gLeoAQzEUvIFZQTLQNxhFfiiVNNaXbfZ8HgKEPtSTvpaglXpnCo9COtawFeKPtaKmENpRj5V3mP0EOhtt4w_MpLhHekN",
"domain": ".x.com",
"path": "/",
"secure": true,
"httpOnly": true,
"sameSite": "Lax"
}
]

View File

@ -0,0 +1,249 @@
#!/usr/bin/env python3
"""
X/Twitter Feed Scraper using Playwright
Scrapes specific accounts for trading-related posts.
Uses saved Chrome session cookies for authentication.
"""
import json
import os
import sys
import time
from datetime import datetime, timezone
from pathlib import Path
ACCOUNTS = [
"browomo", "ArchiveExplorer", "noisyb0y1", "krajekis",
"Shelpid_WI3M", "polyaboretum", "0xashensoul",
]
TRADING_KEYWORDS = [
"polymarket", "trade", "profit", "wallet", "arbitrage", "signal",
"crypto", "bitcoin", "ethereum", "solana", "strategy", "edge",
"bet", "position", "stock", "market", "pnl", "alpha",
"$", "usdc", "defi", "token", "copy", "whale", "degen",
"short", "long", "bullish", "bearish", "portfolio",
]
DATA_DIR = Path(__file__).parent.parent / "data" / "x-feed"
DATA_DIR.mkdir(parents=True, exist_ok=True)
COOKIE_FILE = Path(__file__).parent / "x_cookies.json"
TELEGRAM_BOT_TOKEN = os.environ.get("TELEGRAM_BOT_TOKEN", "")
TELEGRAM_CHAT_ID = os.environ.get("TELEGRAM_CHAT_ID", "6443752046")
def send_telegram(message):
if not TELEGRAM_BOT_TOKEN:
print(f"[ALERT] {message}")
return
import urllib.request
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
data = json.dumps({"chat_id": TELEGRAM_CHAT_ID, "text": message, "parse_mode": "HTML"}).encode()
req = urllib.request.Request(url, data=data, headers={"Content-Type": "application/json"})
try:
urllib.request.urlopen(req, timeout=10)
except Exception as e:
print(f"Telegram error: {e}")
def save_cookies(context):
cookies = context.cookies()
COOKIE_FILE.write_text(json.dumps(cookies, indent=2))
print(f"Saved {len(cookies)} cookies")
def load_cookies(context):
if COOKIE_FILE.exists():
cookies = json.loads(COOKIE_FILE.read_text())
context.add_cookies(cookies)
print(f"Loaded {len(cookies)} cookies")
return True
return False
def export_cookies_from_chrome():
"""One-time: grab cookies from the running Chrome debug instance."""
import http.client, websocket as ws_mod
conn = http.client.HTTPConnection("localhost", 9222)
conn.request("GET", "/json")
tabs = json.loads(conn.getresponse().read())
x_tab = None
for t in tabs:
if "x.com" in t.get("url", ""):
x_tab = t
break
if not x_tab:
print("No X tab found in Chrome debug")
return []
ws = ws_mod.create_connection(x_tab["webSocketDebuggerUrl"], timeout=10)
ws.send(json.dumps({"id": 1, "method": "Network.getAllCookies"}))
result = json.loads(ws.recv())
all_cookies = result.get("result", {}).get("cookies", [])
ws.close()
# Filter for x.com cookies and convert to Playwright format
x_cookies = []
for c in all_cookies:
if "x.com" in c.get("domain", "") or "twitter.com" in c.get("domain", ""):
x_cookies.append({
"name": c["name"],
"value": c["value"],
"domain": c["domain"],
"path": c.get("path", "/"),
"secure": c.get("secure", False),
"httpOnly": c.get("httpOnly", False),
"sameSite": c.get("sameSite", "Lax"),
})
COOKIE_FILE.write_text(json.dumps(x_cookies, indent=2))
print(f"Exported {len(x_cookies)} X cookies from Chrome")
return x_cookies
def scrape_account(page, account, max_scroll=5):
"""Scrape recent posts from a single account."""
posts = []
try:
page.goto(f"https://x.com/{account}", wait_until="networkidle", timeout=15000)
except:
try:
page.goto(f"https://x.com/{account}", wait_until="domcontentloaded", timeout=10000)
page.wait_for_timeout(3000)
except Exception as e:
print(f" Failed to load @{account}: {e}")
return posts
seen_texts = set()
for scroll in range(max_scroll):
articles = page.query_selector_all("article")
for article in articles:
try:
text = article.inner_text()[:800]
# Deduplicate
sig = text[:100]
if sig in seen_texts:
continue
seen_texts.add(sig)
# Extract links
links = article.query_selector_all("a")
urls = [l.get_attribute("href") for l in links if l.get_attribute("href")]
posts.append({
"account": account,
"text": text,
"urls": urls[:5],
"scraped_at": datetime.now(timezone.utc).isoformat(),
})
except:
continue
# Scroll down
page.evaluate("window.scrollBy(0, 1500)")
page.wait_for_timeout(1500)
return posts
def is_trading_related(text):
text_lower = text.lower()
return any(kw in text_lower for kw in TRADING_KEYWORDS)
def main():
from playwright.sync_api import sync_playwright
print(f"=== X Feed Scraper (Playwright) ===")
print(f"Time: {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M UTC')}")
# Export cookies from Chrome if we don't have them yet
if not COOKIE_FILE.exists():
print("No cookies found — exporting from Chrome debug session...")
export_cookies_from_chrome()
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
context = browser.new_context(
user_agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
viewport={"width": 1280, "height": 900},
)
load_cookies(context)
page = context.new_page()
all_posts = []
trading_posts = []
for account in ACCOUNTS:
print(f"\nScraping @{account}...", end=" ", flush=True)
posts = scrape_account(page, account)
print(f"{len(posts)} posts")
for post in posts:
all_posts.append(post)
if is_trading_related(post["text"]):
trading_posts.append(post)
browser.close()
print(f"\n{'='*50}")
print(f"Total posts: {len(all_posts)}")
print(f"Trading-related: {len(trading_posts)}")
# Save results
timestamp = datetime.now(timezone.utc).strftime("%Y%m%d-%H%M")
out_file = DATA_DIR / f"scan-{timestamp}.json"
out_file.write_text(json.dumps({
"timestamp": datetime.now(timezone.utc).isoformat(),
"total_posts": len(all_posts),
"trading_posts": len(trading_posts),
"posts": trading_posts,
}, indent=2))
print(f"Saved to {out_file}")
# Check for new posts we haven't seen before
seen_file = DATA_DIR / "seen_posts.json"
seen = set()
if seen_file.exists():
try:
seen = set(json.loads(seen_file.read_text()))
except:
pass
new_posts = []
for post in trading_posts:
sig = post["text"][:150]
if sig not in seen:
new_posts.append(post)
seen.add(sig)
seen_file.write_text(json.dumps(list(seen)[-5000:])) # Keep last 5000
if new_posts:
print(f"\n🔔 {len(new_posts)} NEW trading posts!")
for post in new_posts[:5]:
lines = post["text"].split("\n")
author = f"@{post['account']}"
snippet = post["text"][:200].replace("\n", " ")
print(f"\n {author}: {snippet}")
# Alert on Telegram
msg = f"🔍 <b>New from {author}</b>\n\n{snippet[:300]}"
if post.get("urls"):
x_urls = [u for u in post["urls"] if "x.com" in u or "twitter.com" in u]
if x_urls:
msg += f"\n\n{x_urls[0]}"
send_telegram(msg)
else:
print("\nNo new trading posts since last scan.")
if __name__ == "__main__":
main()

View File

@ -1,18 +1,10 @@
{
"cash": 53477.43000000002,
"cash": 60255.30020874026,
"positions": {
"DUOL": {
"shares": 57,
"avg_cost": 116.35,
"current_price": 116.35,
"entry_date": "2026-02-09T10:55:58.243598",
"entry_reason": "GARP signal: PE=14.65, FwdPE=14.71, RevGr=41.1%, EPSGr=1114.3%, RSI=23.44",
"trailing_stop": 104.715
},
"ALLY": {
"shares": 156,
"avg_cost": 42.65,
"current_price": 42.65,
"current_price": 42.040000915527344,
"entry_date": "2026-02-09T10:55:58.244488",
"entry_reason": "GARP signal: PE=18.0, FwdPE=6.76, RevGr=12.0%, EPSGr=265.4%, RSI=53.23",
"trailing_stop": 38.385
@ -20,7 +12,7 @@
"JHG": {
"shares": 138,
"avg_cost": 48.21,
"current_price": 48.21,
"current_price": 48.20000076293945,
"entry_date": "2026-02-09T10:55:58.245351",
"entry_reason": "GARP signal: PE=9.22, FwdPE=9.96, RevGr=61.3%, EPSGr=243.6%, RSI=68.71",
"trailing_stop": 43.389
@ -28,31 +20,31 @@
"INCY": {
"shares": 61,
"avg_cost": 108.69,
"current_price": 108.69,
"current_price": 109.02999877929688,
"entry_date": "2026-02-09T10:55:58.246289",
"entry_reason": "GARP signal: PE=18.42, FwdPE=13.76, RevGr=20.0%, EPSGr=290.7%, RSI=63.48",
"trailing_stop": 97.821
"trailing_stop": 98.12699890136719
},
"PINS": {
"shares": 332,
"avg_cost": 20.06,
"current_price": 20.06,
"current_price": 20.139999389648438,
"entry_date": "2026-02-09T10:55:58.247262",
"entry_reason": "GARP signal: PE=7.04, FwdPE=10.61, RevGr=16.8%, EPSGr=225.0%, RSI=19.14",
"trailing_stop": 18.054
"trailing_stop": 18.125999450683594
},
"EXEL": {
"shares": 152,
"avg_cost": 43.8,
"current_price": 43.8,
"current_price": 43.95000076293945,
"entry_date": "2026-02-09T10:55:58.252764",
"entry_reason": "GARP signal: PE=18.4, FwdPE=12.76, RevGr=10.8%, EPSGr=72.5%, RSI=50.12",
"trailing_stop": 39.42
"trailing_stop": 39.555000686645506
},
"CART": {
"shares": 187,
"avg_cost": 35.49,
"current_price": 35.49,
"current_price": 35.150001525878906,
"entry_date": "2026-02-09T10:55:58.254418",
"entry_reason": "GARP signal: PE=19.5, FwdPE=9.05, RevGr=10.2%, EPSGr=21.1%, RSI=37.75",
"trailing_stop": 31.941000000000003

View File

@ -1,10 +1,10 @@
[
{
"date": "2026-02-09",
"total_value": 100000.0,
"total_pnl": 0.0,
"pnl_pct": 0.0,
"cash": 53477.43,
"num_positions": 7
"total_value": 100055.9,
"total_pnl": 55.9,
"pnl_pct": 0.06,
"cash": 60255.3,
"num_positions": 6
}
]

View File

@ -61,5 +61,16 @@
"cost": 6636.63,
"reason": "GARP signal: PE=19.5, FwdPE=9.05, RevGr=10.2%, EPSGr=21.1%, RSI=37.75",
"timestamp": "2026-02-09T10:55:58.254721"
},
{
"action": "SELL",
"ticker": "DUOL",
"shares": 57,
"price": 118.91000366210938,
"proceeds": 6777.87,
"realized_pnl": 145.92,
"entry_price": 116.35,
"reason": "No longer passes GARP filter",
"timestamp": "2026-02-09T15:36:18.884898"
}
]

View File

@ -194,5 +194,117 @@
"ticker": "WTFC",
"reason": "RSI too high (72.6 > 70)",
"details": {}
},
{
"timestamp": "2026-02-09T15:36:18.885237",
"action": "SELL",
"ticker": "DUOL",
"reason": "No longer passes GARP filter",
"details": {
"success": true,
"ticker": "DUOL",
"shares": 57,
"price": 118.91000366210938,
"proceeds": 6777.87,
"realized_pnl": 145.92
}
},
{
"timestamp": "2026-02-09T15:36:19.302964",
"action": "SKIP",
"ticker": "VLY",
"reason": "RSI too high (78.3 > 70)",
"details": {}
},
{
"timestamp": "2026-02-09T15:36:19.303492",
"action": "SKIP",
"ticker": "FHN",
"reason": "RSI too high (72.4 > 70)",
"details": {}
},
{
"timestamp": "2026-02-09T15:36:19.304721",
"action": "SKIP",
"ticker": "FNB",
"reason": "RSI too high (71.0 > 70)",
"details": {}
},
{
"timestamp": "2026-02-09T15:36:19.305710",
"action": "SKIP",
"ticker": "SSB",
"reason": "RSI too high (89.0 > 70)",
"details": {}
},
{
"timestamp": "2026-02-09T15:36:19.306687",
"action": "SKIP",
"ticker": "WBS",
"reason": "RSI too high (82.0 > 70)",
"details": {}
},
{
"timestamp": "2026-02-09T15:36:19.307754",
"action": "SKIP",
"ticker": "ONB",
"reason": "RSI too high (77.6 > 70)",
"details": {}
},
{
"timestamp": "2026-02-09T15:36:19.308706",
"action": "SKIP",
"ticker": "WAL",
"reason": "RSI too high (71.7 > 70)",
"details": {}
},
{
"timestamp": "2026-02-09T15:36:19.309624",
"action": "SKIP",
"ticker": "ZION",
"reason": "RSI too high (73.3 > 70)",
"details": {}
},
{
"timestamp": "2026-02-09T15:36:19.310657",
"action": "SKIP",
"ticker": "CFG",
"reason": "RSI too high (78.5 > 70)",
"details": {}
},
{
"timestamp": "2026-02-09T15:36:19.311641",
"action": "SKIP",
"ticker": "UBSI",
"reason": "RSI too high (77.5 > 70)",
"details": {}
},
{
"timestamp": "2026-02-09T15:36:19.312722",
"action": "SKIP",
"ticker": "EWBC",
"reason": "RSI too high (78.6 > 70)",
"details": {}
},
{
"timestamp": "2026-02-09T15:36:19.313689",
"action": "SKIP",
"ticker": "FITB",
"reason": "Too close to 52wk high (1.9% away)",
"details": {}
},
{
"timestamp": "2026-02-09T15:36:19.314689",
"action": "SKIP",
"ticker": "BAC",
"reason": "RSI too high (78.1 > 70)",
"details": {}
},
{
"timestamp": "2026-02-09T15:36:19.315714",
"action": "SKIP",
"ticker": "WTFC",
"reason": "RSI too high (70.2 > 70)",
"details": {}
}
]

View File

@ -1,356 +1,338 @@
{
"date": "2026-02-09",
"timestamp": "2026-02-09T10:55:58.242176",
"timestamp": "2026-02-09T15:36:18.290971",
"total_scanned": 902,
"candidates_found": 21,
"candidates_found": 20,
"candidates": [
{
"ticker": "DUOL",
"price": 116.35,
"market_cap": 5378552832,
"market_cap_b": 5.4,
"trailing_pe": 14.65,
"forward_pe": 14.71,
"peg_ratio": null,
"revenue_growth": 41.1,
"earnings_growth": 1114.3,
"roe": 36.2,
"quick_ratio": 2.6,
"debt_to_equity": 7.4,
"rsi": 23.44,
"week52_high": 544.93,
"pct_from_52wk_high": 78.6,
"score": -100.83
},
{
"ticker": "ALLY",
"price": 42.65,
"market_cap": 13158768640,
"market_cap_b": 13.2,
"trailing_pe": 18.0,
"forward_pe": 6.76,
"price": 42.04,
"market_cap": 12969046016,
"market_cap_b": 13.0,
"trailing_pe": 17.74,
"forward_pe": 6.66,
"peg_ratio": null,
"revenue_growth": 12.0,
"earnings_growth": 265.4,
"roe": 5.8,
"quick_ratio": null,
"debt_to_equity": null,
"rsi": 53.23,
"rsi": 49.52,
"week52_high": 47.27,
"pct_from_52wk_high": 9.8,
"score": -20.98
"pct_from_52wk_high": 11.1,
"score": -21.08
},
{
"ticker": "JHG",
"price": 48.21,
"market_cap": 7447323136,
"price": 48.2,
"market_cap": 7445763584,
"market_cap_b": 7.4,
"trailing_pe": 9.22,
"forward_pe": 9.96,
"forward_pe": 9.95,
"peg_ratio": null,
"revenue_growth": 61.3,
"earnings_growth": 243.6,
"roe": 16.2,
"quick_ratio": 69.46,
"debt_to_equity": 6.5,
"rsi": 68.71,
"rsi": 68.18,
"week52_high": 49.42,
"pct_from_52wk_high": 2.4,
"score": -20.529999999999998
"pct_from_52wk_high": 2.5,
"score": -20.54
},
{
"ticker": "INCY",
"price": 108.69,
"market_cap": 21338314752,
"market_cap_b": 21.3,
"trailing_pe": 18.42,
"forward_pe": 13.76,
"price": 109.03,
"market_cap": 21405063168,
"market_cap_b": 21.4,
"trailing_pe": 18.48,
"forward_pe": 13.81,
"peg_ratio": null,
"revenue_growth": 20.0,
"earnings_growth": 290.7,
"roe": 30.4,
"quick_ratio": 2.86,
"debt_to_equity": 0.9,
"rsi": 63.48,
"rsi": 64.03,
"week52_high": 112.29,
"pct_from_52wk_high": 3.2,
"score": -17.310000000000002
"pct_from_52wk_high": 2.9,
"score": -17.259999999999998
},
{
"ticker": "PINS",
"price": 20.06,
"market_cap": 13635989504,
"market_cap_b": 13.6,
"trailing_pe": 7.04,
"forward_pe": 10.61,
"price": 20.14,
"market_cap": 13693783040,
"market_cap_b": 13.7,
"trailing_pe": 7.07,
"forward_pe": 10.66,
"peg_ratio": null,
"revenue_growth": 16.8,
"earnings_growth": 225.0,
"roe": 51.5,
"quick_ratio": 8.14,
"debt_to_equity": 4.3,
"rsi": 19.14,
"rsi": 19.93,
"week52_high": 40.38,
"pct_from_52wk_high": 50.3,
"score": -13.57
"pct_from_52wk_high": 50.1,
"score": -13.52
},
{
"ticker": "VLY",
"price": 13.72,
"market_cap": 7647972352,
"price": 13.7,
"market_cap": 7639607296,
"market_cap_b": 7.6,
"trailing_pe": 13.58,
"forward_pe": 9.2,
"trailing_pe": 13.56,
"forward_pe": 9.19,
"peg_ratio": null,
"revenue_growth": 38.3,
"earnings_growth": 66.3,
"roe": 7.8,
"quick_ratio": null,
"debt_to_equity": null,
"rsi": 78.6,
"rsi": 78.34,
"week52_high": 13.79,
"pct_from_52wk_high": 0.5,
"score": -1.2600000000000002
"pct_from_52wk_high": 0.7,
"score": -1.27
},
{
"ticker": "FHN",
"price": 26.33,
"market_cap": 12967198720,
"market_cap_b": 13.0,
"trailing_pe": 14.08,
"forward_pe": 11.23,
"price": 26.03,
"market_cap": 12817018880,
"market_cap_b": 12.8,
"trailing_pe": 13.92,
"forward_pe": 11.1,
"peg_ratio": null,
"revenue_growth": 23.7,
"earnings_growth": 74.9,
"roe": 10.9,
"quick_ratio": null,
"debt_to_equity": null,
"rsi": 76.1,
"rsi": 72.36,
"week52_high": 26.56,
"pct_from_52wk_high": 0.8,
"score": 1.37
"pct_from_52wk_high": 2.0,
"score": 1.2399999999999993
},
{
"ticker": "FNB",
"price": 19.05,
"market_cap": 6822501376,
"price": 18.92,
"market_cap": 6775944192,
"market_cap_b": 6.8,
"trailing_pe": 12.21,
"forward_pe": 9.73,
"trailing_pe": 12.13,
"forward_pe": 9.67,
"peg_ratio": null,
"revenue_growth": 26.4,
"earnings_growth": 56.5,
"roe": 8.7,
"quick_ratio": null,
"debt_to_equity": null,
"rsi": 71.92,
"rsi": 70.99,
"week52_high": 19.14,
"pct_from_52wk_high": 0.4,
"score": 1.4400000000000004
"pct_from_52wk_high": 1.1,
"score": 1.38
},
{
"ticker": "SSB",
"price": 107.67,
"market_cap": 10821986304,
"price": 107.18,
"market_cap": 10773236736,
"market_cap_b": 10.8,
"trailing_pe": 13.68,
"forward_pe": 10.18,
"trailing_pe": 13.62,
"forward_pe": 10.13,
"peg_ratio": null,
"revenue_growth": 53.2,
"earnings_growth": 30.9,
"roe": 10.7,
"quick_ratio": null,
"debt_to_equity": null,
"rsi": 92.25,
"rsi": 89.03,
"week52_high": 108.46,
"pct_from_52wk_high": 0.7,
"score": 1.7699999999999996
"pct_from_52wk_high": 1.2,
"score": 1.7200000000000006
},
{
"ticker": "WBS",
"price": 73.28,
"market_cap": 11818547200,
"price": 73.21,
"market_cap": 11808063488,
"market_cap_b": 11.8,
"trailing_pe": 12.42,
"forward_pe": 9.79,
"trailing_pe": 12.41,
"forward_pe": 9.78,
"peg_ratio": null,
"revenue_growth": 18.2,
"earnings_growth": 53.4,
"roe": 10.8,
"quick_ratio": null,
"debt_to_equity": null,
"rsi": 82.13,
"rsi": 82.05,
"week52_high": 73.5,
"pct_from_52wk_high": 0.3,
"score": 2.6299999999999994
},
{
"ticker": "WAL",
"price": 96.21,
"market_cap": 10588263424,
"market_cap_b": 10.6,
"trailing_pe": 11.02,
"forward_pe": 8.09,
"peg_ratio": null,
"revenue_growth": 16.6,
"earnings_growth": 32.9,
"roe": 13.5,
"quick_ratio": null,
"debt_to_equity": null,
"rsi": 71.81,
"week52_high": 96.94,
"pct_from_52wk_high": 0.8,
"score": 3.1399999999999997
"pct_from_52wk_high": 0.4,
"score": 2.6199999999999997
},
{
"ticker": "ONB",
"price": 25.93,
"market_cap": 10132744192,
"market_cap_b": 10.1,
"trailing_pe": 14.49,
"forward_pe": 9.04,
"price": 25.67,
"market_cap": 10031142912,
"market_cap_b": 10.0,
"trailing_pe": 14.34,
"forward_pe": 8.95,
"peg_ratio": null,
"revenue_growth": 41.4,
"earnings_growth": 17.2,
"roe": 9.0,
"quick_ratio": null,
"debt_to_equity": null,
"rsi": 81.24,
"rsi": 77.64,
"week52_high": 26.17,
"pct_from_52wk_high": 1.9,
"score": 3.09
},
{
"ticker": "WAL",
"price": 96.08,
"market_cap": 10573956096,
"market_cap_b": 10.6,
"trailing_pe": 11.01,
"forward_pe": 8.08,
"peg_ratio": null,
"revenue_growth": 16.6,
"earnings_growth": 32.9,
"roe": 13.5,
"quick_ratio": null,
"debt_to_equity": null,
"rsi": 71.66,
"week52_high": 96.99,
"pct_from_52wk_high": 0.9,
"score": 3.1799999999999997
"score": 3.13
},
{
"ticker": "EXEL",
"price": 43.8,
"market_cap": 11791070208,
"price": 43.95,
"market_cap": 11831451648,
"market_cap_b": 11.8,
"trailing_pe": 18.4,
"forward_pe": 12.76,
"trailing_pe": 18.47,
"forward_pe": 12.8,
"peg_ratio": null,
"revenue_growth": 10.8,
"earnings_growth": 72.5,
"roe": 30.6,
"quick_ratio": 3.5,
"debt_to_equity": 8.2,
"rsi": 50.12,
"rsi": 51.02,
"week52_high": 49.62,
"pct_from_52wk_high": 11.7,
"score": 4.43
"pct_from_52wk_high": 11.4,
"score": 4.470000000000001
},
{
"ticker": "ZION",
"price": 65.29,
"market_cap": 9640263680,
"price": 65.16,
"market_cap": 9621069824,
"market_cap_b": 9.6,
"trailing_pe": 10.86,
"forward_pe": 9.99,
"trailing_pe": 10.84,
"forward_pe": 9.97,
"peg_ratio": null,
"revenue_growth": 13.6,
"earnings_growth": 31.4,
"roe": 13.5,
"quick_ratio": null,
"debt_to_equity": null,
"rsi": 74.03,
"rsi": 73.29,
"week52_high": 66.18,
"pct_from_52wk_high": 1.3,
"score": 5.49
"pct_from_52wk_high": 1.5,
"score": 5.470000000000001
},
{
"ticker": "CART",
"price": 35.49,
"market_cap": 9349425152,
"price": 35.15,
"market_cap": 9259855872,
"market_cap_b": 9.3,
"trailing_pe": 19.5,
"forward_pe": 9.05,
"trailing_pe": 19.31,
"forward_pe": 8.97,
"peg_ratio": null,
"revenue_growth": 10.2,
"earnings_growth": 21.1,
"roe": 15.3,
"quick_ratio": 3.33,
"debt_to_equity": 1.0,
"rsi": 37.75,
"rsi": 36.01,
"week52_high": 53.5,
"pct_from_52wk_high": 33.7,
"score": 5.92
"pct_from_52wk_high": 34.3,
"score": 5.84
},
{
"ticker": "CFG",
"price": 68.17,
"market_cap": 29278072832,
"market_cap_b": 29.3,
"trailing_pe": 17.66,
"forward_pe": 10.82,
"price": 67.7,
"market_cap": 29076213760,
"market_cap_b": 29.1,
"trailing_pe": 17.54,
"forward_pe": 10.75,
"peg_ratio": null,
"revenue_growth": 10.7,
"earnings_growth": 35.9,
"roe": 7.2,
"quick_ratio": null,
"debt_to_equity": null,
"rsi": 80.86,
"rsi": 78.47,
"week52_high": 68.65,
"pct_from_52wk_high": 0.7,
"score": 6.16
"pct_from_52wk_high": 1.4,
"score": 6.09
},
{
"ticker": "UBSI",
"price": 45.32,
"market_cap": 6316939264,
"price": 45.06,
"market_cap": 6280699392,
"market_cap_b": 6.3,
"trailing_pe": 13.86,
"forward_pe": 12.03,
"trailing_pe": 13.78,
"forward_pe": 11.96,
"peg_ratio": null,
"revenue_growth": 22.1,
"earnings_growth": 32.1,
"roe": 8.9,
"quick_ratio": null,
"debt_to_equity": null,
"rsi": 80.0,
"rsi": 77.51,
"week52_high": 45.93,
"pct_from_52wk_high": 1.3,
"score": 6.61
"pct_from_52wk_high": 1.9,
"score": 6.54
},
{
"ticker": "EWBC",
"price": 123.19,
"market_cap": 16949170176,
"price": 122.56,
"market_cap": 16862490624,
"market_cap_b": 16.9,
"trailing_pe": 12.94,
"forward_pe": 11.24,
"trailing_pe": 12.87,
"forward_pe": 11.18,
"peg_ratio": null,
"revenue_growth": 21.6,
"earnings_growth": 21.3,
"roe": 15.9,
"quick_ratio": null,
"debt_to_equity": null,
"rsi": 79.27,
"rsi": 78.61,
"week52_high": 123.82,
"pct_from_52wk_high": 0.5,
"score": 6.949999999999999
"pct_from_52wk_high": 1.0,
"score": 6.890000000000001
},
{
"ticker": "FITB",
"price": 54.38,
"market_cap": 48944635904,
"price": 54.33,
"market_cap": 48899633152,
"market_cap_b": 48.9,
"trailing_pe": 15.41,
"forward_pe": 11.09,
"trailing_pe": 15.39,
"forward_pe": 11.08,
"peg_ratio": null,
"revenue_growth": 11.5,
"earnings_growth": 20.8,
"roe": 12.2,
"quick_ratio": null,
"debt_to_equity": null,
"rsi": 66.02,
"rsi": 65.77,
"week52_high": 55.36,
"pct_from_52wk_high": 1.8,
"score": 7.859999999999999
"pct_from_52wk_high": 1.9,
"score": 7.85
},
{
"ticker": "BAC",
"price": 56.43,
"market_cap": 412079849472,
"market_cap_b": 412.1,
"price": 56.41,
"market_cap": 411933769728,
"market_cap_b": 411.9,
"trailing_pe": 14.81,
"forward_pe": 11.38,
"peg_ratio": null,
@ -359,28 +341,28 @@
"roe": 10.2,
"quick_ratio": null,
"debt_to_equity": null,
"rsi": 78.3,
"rsi": 78.1,
"week52_high": 57.55,
"pct_from_52wk_high": 1.9,
"pct_from_52wk_high": 2.0,
"score": 7.970000000000001
},
{
"ticker": "WTFC",
"price": 159.71,
"market_cap": 10696563712,
"market_cap_b": 10.7,
"trailing_pe": 14.0,
"forward_pe": 11.91,
"price": 158.57,
"market_cap": 10620212224,
"market_cap_b": 10.6,
"trailing_pe": 13.9,
"forward_pe": 11.82,
"peg_ratio": null,
"revenue_growth": 10.5,
"earnings_growth": 19.4,
"roe": 12.1,
"quick_ratio": null,
"debt_to_equity": null,
"rsi": 72.56,
"rsi": 70.23,
"week52_high": 162.96,
"pct_from_52wk_high": 2.0,
"score": 8.92
"pct_from_52wk_high": 2.7,
"score": 8.83
}
]
}