Trading Operationsvictorngoma.com

Hi thereRunbook · SPX Strategy

SPX Strategy Operations

How the SPX credit-spread system works today: the strategy stack, the server-side premium stop safety net, the v3 observe-mode workflow, and the roadmap. ← Back to Runbook home

Paper trading. Everything on this page operates on paper money via Tastytrade's sandbox. No real dollars move. All times are Central Time (Texas) — the session runs 8:30a–3:00p CT and every script is coded to America/Chicago explicitly.
The strategy stack (as of 2026-07-30)
What is running, and in what mode
  • v2.2 Directional (spx_0dte_1min rail) — LIVE paper. 0DTE credit spreads with OTM cushion strikes (VIX-scaled), daily-SMA20 trend gate, VIX 16–18 chop skip, close-confirmed stop.
  • Dip Harvester v1.1 (spx_0dte_pt50 rail) — LIVE paper. 1-minute mean reversion in the direction of the daily trend: extreme washout (RSI5 < 10 + Bollinger break) → sell a put spread below the washout low. Mirrored for pops in a downtrend.
  • v3 Premium Harvester — OBSERVE MODE (webhooks off). The lead candidate: one script that picks the side from the daily trend, sells flushes (VWAP z-score), adds a quiet-day carry at 11:00a CT, sizes strikes at 1.1× the remaining-day expected move, and picks width from VIX. Run it on the 5-minute SP:SPX chart — that timeframe won Victor's robustness test (~6 months of history, all three engines positive).
  • Retired: the 1DTE end-of-day strategy (still negative even with-trend) and the old 10-ITM entry logic (the single biggest loss driver in the 176-trade study).
The breakeven math that drives every decision

Credit-spread selling wins small and loses big. Our measured averages: wins of roughly $150–$190, losses of roughly $750–$1,600. At those numbers the system needs an 84–87% win rate just to break even.

That leads to the two operating rules:

  • Tail size is THE lever. Shrinking the worst loss from $1,600 to $800 lowers the required win rate more than any entry tweak raises the actual one. This is why the server premium stop (below) exists.
  • Only trade with the daily trend. The 176-trade study split +$5.7k (with-trend) vs −$14.6k (counter-trend). Every current script enforces this with a daily SMA20 gate.
The server premium stop (Phase 1 — live since 2026-07-30)
What it is and how it works

A smoke alarm for every open SPX spread, running on the server (not on the chart):

  1. Every 10 minutes during market hours the server asks the broker what it would really cost to buy back each open spread.
  2. It compares that cost to the credit collected at entry.
  3. If the buyback cost reaches 2.5× the entry credit, the server closes the trade immediately at market — it cancels the resting profit-target order first, then buys the spread back, logs the loss, and journals the exit as SERVER_STOP_LOSS.

Worked example: collect $5.00 at entry → the stop fires if buyback reaches $12.50 → loss ≈ (12.50 − 5.00) × 100 = −$750, instead of drifting toward a −$1,000–$1,600 max-width loss.

Because it watches real quotes, the protection is identical no matter what chart timeframe the Pine script runs on. Chart stops only confirm on bar close — slow on a 5-minute chart; the server doesn't wait.

It protects all five SPX rails: v2.2, Dip Harvester, both 15-min variants, and the (retired) 1DTE — anything with an open position.

Tune, loosen, or disable the premium stop

The config lives in /home/victor/spx-server/allocations.json, block spread_premium_stop:

  • stop_multiple — currently 2.5. Raise to 3.0 for fewer (but larger) stop-outs; the agreed sane range is 2.5–3.0.
  • stop_multiple_overrides — per-strategy exceptions, e.g. {"spx_0dte_pt50": 3.0}.
  • enabled — set false to turn the whole thing off (not recommended).

After editing, restart the SPX brain (after hours). SSH in first — prompt must say victor@spx-server:

kill -9 $(pgrep -f "spx-server/server.py" | head -1)

Wait ~15 seconds, then confirm it's healthy:

curl -s http://127.0.0.1:5005/health | head -c 200; echo; grep "Spread premium stop" /var/log/spx-server.log | tail -1

The log line shows the settings the server actually loaded — check the multiple matches what you set.

Never use a plain kill — the service only auto-restarts after an "accidental" death (kill -9). A polite kill leaves it down.
Verify a premium-stop fire (do this after the first one)

When the stop fires you'll want proof everything downstream recorded it correctly:

  1. Server log:
    grep "PREMIUM_STOP_FIRED" /var/log/spx-server.log | tail -5
  2. Journal: the trade's exit row should read SERVER_STOP_LOSS with reason server_premium_stop:
    grep "server_premium_stop" /home/victor/spx-server/journal/trades_journal_2026.csv | tail -3
  3. Panel: after 5:30p CT (the daily ledger rebuild), the trade should appear on the SPX pages as a closed loss of roughly (multiple − 1) × credit × 100. If it still shows open the next day, something is wrong — investigate.
v3 Premium Harvester — observe-mode workflow
Chart setup and what the table tells you
  • Chart: SP:SPX, 5-minute. Indicator: "SPX Premium Harvester — v3 (observe mode)".
  • The status table sits top-right. Top rows = live context (side, z-score, VIX → width, expected move, entries). Bottom rows = the instant rough backtest: Est P&L, W/L, average win/loss, worst loss, and per-engine attribution (Flush / Fade / Carry).
  • Treat Est P&L as optimistic. It books profit-targets at 50% of credit instantly; real server fills lag. A table showing 96–98% wins realistically means ~88–92% live — still above breakeven, but don't celebrate the table number.
JSON label verification (before arming webhooks)

v3 has a debug switch: indicator Settings → Inputs → Webhook group → "Show JSON labels on chart".

When ON, every signal bar prints the exact JSON payload the webhook would send — the same string, byte for byte. Use it to eyeball, before going live:

  • Option symbols — legs read like SPXW 260730P00007350: right root, today's date, P for put spreads / C for call spreads, strike padded to 8 digits.
  • Strikes make sense — short strike beyond the expected move, long strike exactly one width farther out.
  • Signal types — entries say ENTRY_BULL/ENTRY_BEAR; profit-take exits say EXIT_PT; stop and end-of-day exits say EXIT_EOD (the stop variant carries "reason":"stop_loss_proxy").
  • position_id is consistent between a trade's entry and its exits.

The labels work while webhooks are OFF — that's the point. Verify first, arm later. Turn the switch off afterward to keep the chart clean.

Roadmap
Phases: where we are
  • Phase 1 — DONE (2026-07-30): server premium stop live on all SPX rails. Makes the worst-case loss timeframe-independent.
  • Phase 2 — IN PROGRESS: v3 observing on the 5-minute chart. Goal: 2–3 clean days where the signals it prints match what we'd want a server to do.
  • Phase 3 — NEXT: assign v3 a server rail (its own strategy id in server.py or a retired slot), point a TradingView alert with webhooks ON at it, paper trade it, and compare against v2.2 + Dip Harvester before any capital decisions.
Restricted access · Operations runbook · victorngoma.com