Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
b4a2f17
feat(report-gen): per-signal SEO metadata for /signals/{ticker} pages
DevDizzle Jun 1, 2026
b9f6377
fix(blog-generator): resolve publish slug from front matter; surface …
DevDizzle Jun 1, 2026
f1beea1
fix(blog-generator): deterministic schedule fallback for slug resolution
DevDizzle Jun 1, 2026
d3b8db0
docs(handoff): blog pipeline live — 12 posts published, fixes logged
DevDizzle Jun 1, 2026
ec995e7
feat(signal-notifier): remove V/OI gate, widen moneyness cap to 0.13,…
DevDizzle Jun 2, 2026
2aa25a7
docs(sector): persistence contract + decision record for sector/industry
DevDizzle Jun 3, 2026
f8325f4
fix(enrichment,signal-notifier): FRED-outage resilience for the regim…
DevDizzle Jun 3, 2026
cb45f2e
chore(seo): add GSC/GA4 query scripts + gammarips-seo subagent
DevDizzle Jun 3, 2026
690d9fa
feat(signal-notifier): sync closed V5.4 trades to Firestore ledger_tr…
DevDizzle Jun 3, 2026
f5bd0df
feat(signal-ranker): picker case-memory harness (picker_v5)
DevDizzle Jun 3, 2026
2e3e2b6
docs(handoff): V5.5 relabel plan + ledger TAG decision for next session
DevDizzle Jun 4, 2026
0a8477f
fix(signal-notifier): single-source live-VIX fallback on FRED outage
DevDizzle Jun 4, 2026
09ea872
fix(fred): bound all VIXCLS/VXVCLS fetches with cosd — real root-caus…
DevDizzle Jun 4, 2026
0dd21c8
feat(signal-judge): collapse Scorer→Picker into one memory-aware judg…
DevDizzle Jun 4, 2026
d20401a
docs(handoff): mark judge_v6 collapse + signal-judge rename SHIPPED
DevDizzle Jun 4, 2026
62aa11f
fix(blog-generator): drop removed V/OI>2 gate from blog-writer prompt
DevDizzle Jun 4, 2026
f140bfe
docs: reconcile living docs with judge_v6 collapse + signal-judge ren…
DevDizzle Jun 4, 2026
deff6cd
feat(tournament): replace single judge with robust bracket over ALL s…
DevDizzle Jun 4, 2026
2dbb2d5
feat(v6): retire V5.4, truncate ledger, relabel cohort V6_TOURNAMENT
DevDizzle Jun 4, 2026
8a7aa74
fix(scanner): contract selection rewards liquidity, not low OI
DevDizzle Jun 4, 2026
6b2a6dc
fix(pipeline): 13 confirmed bug-hunt fixes corrupting picks
DevDizzle Jun 4, 2026
6a8351f
docs: reconcile all living docs to V6 tournament + 2026-06-04 bug-hunt
DevDizzle Jun 4, 2026
44cdeb8
docs(handoff): tomorrow = webapp V6 reconciliation; record the eval-t…
DevDizzle Jun 4, 2026
2b031b0
copy(v6): reconcile blog-generator narrative to V6 tournament
DevDizzle Jun 5, 2026
c77b572
copy(v6): fix whats-pushed-to-my-phone slot title to 7:30 ET
DevDizzle Jun 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions .claude/agents/gammarips-seo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
name: gammarips-seo
description: Read-only SEO / organic-traffic analyst for gammarips.com. Use proactively for traffic-pattern questions, keyword/content gap analysis, and "how do we win more organic clicks" work. Pulls Google Search Console + GA4 data via scripts/seo/. Read-only — proposes a prioritized action list, never mutates the site, the properties, or trading code.
tools: Read, Bash, Glob, Grep
---

# Role: gammarips-seo (The Organic-Growth Analyst)

You are the SEO and organic-traffic analyst for GammaRips (gammarips.com).
Your job is to turn Search Console + GA4 data into a prioritized list of
moves that win organic clicks. You are read-only: you analyze and
recommend; you never publish content, change the site, or touch trading
code.

## Tools (both read-only, under scripts/seo/)
Always invoke with the project venv python: `scripts/seo/.venv/bin/python`
(the system python lacks the Google client libs).
- `scripts/seo/.venv/bin/python scripts/seo/gsc_query.py --days 28 --dim query|page --limit 50`
— Search Console: clicks, impressions, CTR, average position.
- `scripts/seo/.venv/bin/python scripts/seo/ga4_query.py --days 28 --report landing|source [--channel "Organic Search"]`
— GA4: sessions, users, engaged sessions, avg engagement.

If a script errors on auth/property, do NOT guess credentials. Surface the
exact error and point the user to `scripts/seo/README.md` (SA grants +
`GA4_PROPERTY_ID` / `GSC_SITE_URL`). Never hardcode keys or property ids.

## How to find the wins
1. Pull GSC `query` and `page` over the same window (default 28d).
2. Hunt the classic opportunities, in priority order:
- **Striking distance**: queries at average position 5–15 with high
impressions — small ranking gains here convert to real clicks.
- **Low-CTR / high-impression**: page-1 queries with CTR well below the
position-expected rate — a title/meta-description rewrite problem.
- **Rising queries with no matching page**: demand we don't serve yet —
a content-gap signal.
- **Decaying pages**: clicks/position trending down — refresh candidates.
3. Cross-reference GA4: do the high-impression landing pages actually
engage users once they arrive, or do they bounce? A page that ranks but
doesn't engage is a different fix than one that engages but doesn't rank.

## Output contract
Return a ranked action list. Each item: the query/page, the metric gap
(cite the actual numbers), the hypothesized cause, and a concrete,
cheap-to-execute move (title rewrite, new section, internal link, new
post). Lead with the highest expected-click-gain item.

## Hard rules
- Read-only. Never propose paid ads, link buying, or anything that costs
money or risks the brand — organic only.
- Cite real numbers from the tools; never invent traffic figures.
- Selection discipline: a single good-looking query is not a strategy.
Look for repeated patterns across queries/pages before recommending.
- Stay in your lane: this is marketing analysis, not trading policy. Do
not touch the ledger, the trader, or `docs/DECISIONS/`.
2 changes: 1 addition & 1 deletion .gemini/GEMINI.MD
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Before making meaningful changes, read:
Deeper context (read when relevant): `docs/DECISIONS/` (decision trail), `docs/EVAL-SYSTEM.md`, `docs/TESTING.md`, `docs/research_reports/INTELLIGENCE_BRIEF.md`, `docs/research_reports/FINDINGS_LEDGER.md`.

## Current policy (summary)
**V5.4 "Agent Ranker" is the only active strategy** (promoted 2026-05-08, V5.3 retired same day, ledger TRUNCATED — 246 rows wiped). One signal per day or none, picked by an LLM Scorer→Picker pair (`gemini-3.5-flash` + `gemini-3.1-pro-preview`) hosted at the `signal-ranker` Cloud Run service. **Fail-closed on V5.4 error — no V5.3 fallback.** Trader mechanics unchanged: entry 10:00 ET day-1, −60% option stop, +80% option target, 3-day hold, exit 15:50 ET day-3. Stop wins over target on ambiguous bars (conservative). Hard gates run UPSTREAM of the picker: `enrichment-trigger` (`overnight_score >= 1`, `spread <= 8%`, `directional UOA > $500K`) and `signal-notifier` (`V/OI > 2`, `moneyness 5-10% OTM`, `VIX <= VIX3M`, earnings overlap, `DTE 7-45`, `OI >= 10`, `vol >= 50`). **Daily-cadence fallback (2026-06-01):** on a strict-skip day, `signal-notifier` relaxes ONLY the conviction gates (drops `V/OI > 2`, moneyness floor `0.05 → 0.0`) and emits the best *fillable* candidate — ranker bypassed, `confidence=LOW`, tagged `policy_gate=FALLBACK`; all tradeability gates (OI/vol, regime, earnings, active-days) stay. **Lock-in/trail: leave +80/−60 alone until N≥15** (2026-06-01 decision). Composite weights 60/25/15 flow/regime/narrative (weighted sum). The one-page operator view is `CHEAT-SHEET.md`. Service/table context: `docs/GLOSSARY.md`. Model→function registry: `docs/MODELS.md` (text/scoring on `gemini-3.5-flash` since 2026-05-27). Source of truth for execution policy: `docs/TRADING-STRATEGY.md` + `forward-paper-trader/main.py` + `docs/DECISIONS/2026-05-08-v5-3-retired-v5-4-promoted.md` + `docs/DECISIONS/2026-06-01-daily-cadence-fallback.md`.
**V6 "Tournament" is the only active strategy** (launched 2026-06-04; V5.4 retired same day, `forward_paper_ledger` TRUNCATED — 13 flat closes wiped, avg 0.0%; `policy_version='V6_TOURNAMENT'`). One signal per day or none, picked by a **randomized bracket tournament over ALL enriched signals (no selection gates)** at the `signal-judge` Cloud Run service: 3 independent brackets, each shuffles the pool into batches of ≤10 → top-2 advance → 94→20→4→1; the **consensus** winner across the 3 brackets is the pick (3/3=high, 2/3=medium, 1/3=low). Dead-simple prompt ("make money buying a single option, sell for profit in 3 days") + the daily report for context + per-contract JSON; **no memory, no rubric, no weights** (`tournament_v1`, version 7, `gemini-3.1-pro-preview`; see `docs/DECISIONS/2026-06-04-bracket-tournament.md`). **Fail-closed on error — no fallback.** Trader mechanics unchanged: entry 10:00 ET day-1, −60% option stop, +80% option target, 3-day hold, exit 15:50 ET day-3. Stop wins over target on ambiguous bars (conservative). **Selection gates REMOVED 2026-06-04** — all enriched signals reach the tournament (the old `signal-notifier` moneyness/OI/vol/DTE/V-OI + active-days gates + the daily-cadence fallback are GONE; they choked real winners on stale scan-time data). UPSTREAM only: `enrichment-trigger` defines "enriched" (`overnight_score >= 1`, `spread <= 0.30` — loosened from 8% 2026-06-04 once spreads became real, `directional UOA > $500K`); `signal-notifier` keeps exactly two SAFETY rails — no earnings during the 3-day hold (IV crush) + regime fail-closed (`VIX <= VIX3M`). Every candidate is `assert_no_leakage`-checked before the LLM. **2026-06-04 pipeline bug-hunt (`docs/DECISIONS/2026-06-04-pipeline-bug-fixes.md`): 13 silent data bugs fixed — root cause was `polygon_client` substituting day low/high for missing bid/ask → fake/0% spreads on ~43% of picks (now NULL when unquoted); divergence-flip scoring reordered before conviction signals (was suppressing ~87% of the best setups); technicals lookahead bounded to `scan_date`; stale volume/OI stripped from the judge prompt; liquidity-aware contract selection; trader fill-realism. DEFERRED (need point-in-time data): OI + volume are still session-frozen snapshots, walled off from the judge.** The one-page operator view is `CHEAT-SHEET.md`. Service/table context: `docs/GLOSSARY.md`. Model→function registry: `docs/MODELS.md`. Source of truth for execution policy: `docs/TRADING-STRATEGY.md` + `forward-paper-trader/main.py` + `signal-judge/app/agent.py` + `docs/DECISIONS/2026-06-04-bracket-tournament.md`.

## Ground rules
- NEVER hardcode API keys or secrets in source.
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,9 @@ backtesting_and_research/cache/
# dbt — incomplete/stale project, not in use. Ignore the whole directory.
dbt/
.user.yml

# SEO scripts local venv
scripts/seo/.venv/

# Realized-option-PnL label artifact (738K binary; regenerate via realized_option_label.py)
backtesting_and_research/realized_label.pkl
33 changes: 16 additions & 17 deletions CHEAT-SHEET.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# GammaRips Cheat Sheet — V5.4
# GammaRips Cheat Sheet — V6 "Tournament"

## What this system does
Scans overnight unusual options activity → an LLM agent ranker (Scorer + Picker) chooses one trade per day with a written justification → emails you the pick (with a clickable card linking to `gammarips.com/signals/{ticker}` for rationale) → you execute from your phone at 10 AM → stop + target pre-set → sell at 3:50 PM day-3 if neither hit. Public live-stats panel (`cohort_stats/current` Firestore doc) reflects the V5.4 cohort starting 2026-05-08 (forward_paper_ledger truncated when V5.3 was retired).
Scans overnight unusual options activity → a randomized bracket **tournament** over ALL enriched signals picks one trade per day → emails you the pick (with a clickable card linking to `gammarips.com/signals/{ticker}` for rationale) → you execute from your phone at 10 AM → stop + target pre-set → sell at 3:50 PM day-3 if neither hit. Public live-stats panel (`cohort_stats/current` Firestore doc) reflects the V6 cohort starting 2026-06-04 (forward_paper_ledger truncated when V5.4 was retired; `policy_version='V6_TOURNAMENT'`).

## Your daily routine
| Time | Action |
Expand All @@ -18,21 +18,20 @@ Scans overnight unusual options activity → an LLM agent ranker (Scorer + Picke
- Stop: −60% option premium (GTC stop-limit)
- Target: +80% option premium (GTC limit sell)
- Timeout: 3:50 PM on day 3 (3 full trading days held)
- Fill realism (2026-06-04): symmetric slippage on entry/exit + stale-TIMEOUT and late-fill guards in the simulator

## The signal filter (what reaches your inbox)
Hard gates run UPSTREAM of the agent ranker. Only signals passing ALL get into the candidate pool:
1. Overnight score >= 1
2. Spread <= 8% (tightened from 10% on 2026-05-06 per lit-audit H11)
3. Directional UOA > $500k
4. V/OI ratio > 2.0 at focal strike
5. Moneyness 5–10% OTM (tightened from 15% on 2026-05-06 per lit-audit H12)
6. VIX <= VIX3M (skip entire day if backwardation)
7. Recommended contract OI >= 10 (relaxed from 20 on 2026-05-12 to lift picker-starvation floor)
8. Recommended contract volume >= 50 (relaxed from 100 on 2026-05-12, same reason)
9. DTE 7-45 (added 2026-05-11 at 7-30, widened to 7-45 on 2026-05-12 — picker rubrics penalize >45 DTE)
10. **No earnings near hold window** — exclude any ticker reporting in `[scan_date, entry_day+2 trading days]`. Window includes scan_date to catch AMC prints that contaminate the V/OI signal pre-entry. Literature-anchored hard rule (De Silva et al. 2026 *Review of Finance*: retail loses 5–9% per event). Fail-closed if FMP earnings calendar is unreachable OR returns a non-list payload (quota-exhausted).

Top 10 gate-clean candidates fed to the V5.4 agent ranker. Scorer (`gemini-3.5-flash`, scorer_v5) grades each on three rubrics (1-10): `flow_conviction` (60% weight), `regime_alignment` (25%, must cite the daily report), `narrative_coherence` (15%). HEDGING-tagged flow is hard-capped at flow_conviction ≤4. Top-5 by composite go to the Picker (`gemini-3.1-pro-preview`, picker_v4) — single high-stakes call that returns one ticker + runner-up + justification + confidence enum (`high`/`medium`/`low`). Picker reads top-5 candidate enriched data + Scorer reasoning prose (no raw rubric scores) + the daily report markdown + 14d ledger summary. **No abstain.** **Fail-closed on any error** — no fallback ranker; signal-ranker uptime is the SLO.
V6 has **no selection gates** — every enriched signal enters the tournament. Only the enrichment bar plus two safety rails apply:
1. Overnight score >= 1 (enrichment)
2. Spread <= 30% (enrichment)
3. Directional UOA > $500k (enrichment)
4. **No earnings in the hold window** — exclude any ticker reporting in `[scan_date, entry_day+2 trading days]`. Literature-anchored hard rule (De Silva et al. 2026 *Review of Finance*: retail loses 5–9% per event). Fail-closed if the earnings calendar is unreachable.
5. **VIX <= VIX3M** — skip the entire day if backwardation.

The old moneyness / OI / volume / DTE / V-OI selection gates were **REMOVED 2026-06-04** — the tournament now ranks the full enriched slate directly.

## The pick (V6 Tournament)
The full enriched slate (~94 signals on a typical day) goes to **signal-judge** (`tournament_v1`, `gemini-3.1-pro-preview`). It runs **3 independent randomized brackets**, each: shuffle signals into batches of ≤10 → the LLM picks the top 2 per batch → advance and repeat (~94 → 20 → 4 → 1). Each batch call gets a simple prompt + the daily report + per-contract JSON; **no memory, no rubrics, no weights**. The 3 bracket winners vote: 3/3 agree → `confidence=high`, 2/3 → `medium`, 1/3 → `low`. One ticker emailed. **Fail-closed on any error** — no fallback; signal-judge uptime is the SLO.

## Math
- Deep Research modeled EV +1.8% to +3.2% per trade post-upgrade
Expand All @@ -53,7 +52,7 @@ Top 10 gate-clean candidates fed to the V5.4 agent ranker. Scorer (`gemini-3.5-f
- If EV < 0 → pause, rerun Deep Research angle

## Services (reference only)
`overnight-scanner → enrichment-trigger signal-notifier ← signal-ranker (V5.4 picker) → email + Firestore todays_pick → forward-paper-trader (ledger)`
`overnight-scanner (23:00 ET) → enrichment-trigger (05:30 ET) → overnight-report-generator → signal-notifier (07:30 ET) ← signal-judge (V6 tournament_v1) → email + Firestore todays_pick → forward-paper-trader (ledger)`

## Source of truth
This file + `docs/TRADING-STRATEGY.md` + `docs/DECISIONS/2026-05-08-v5-3-retired-v5-4-promoted.md` + `docs/GLOSSARY.md`. Everything else in `docs/archive/` is historical.
This file + `docs/TRADING-STRATEGY.md` + `docs/GLOSSARY.md`. Everything else in `docs/archive/` is historical.
Loading