How it works

vol-desk is an autonomous options-trading agent that runs unattended against an Alpaca paper account.

The edge

Implied volatility tends to price richer than the volatility that actually gets realized. vol-desk sells defined-risk premium structures — credit spreads and iron condors — on a fixed universe of seven liquid ETFs (SPY, QQQ, IWM, GLD, TLT, XLE, HYG) to harvest that spread, and occasionally buys debit spreads on high-conviction directional signals. Every position has a computable maximum loss before it's ever placed — there are no naked or undefined-risk trades anywhere in the system.

Deterministic control loop, judgment at two points only

The system is a single Python process with an in-process scheduler. Almost everything is ordinary, deterministic code. Two specific decisions are handed to an LLM (via Groq): reading the volatility/trend regime, and picking exact contracts once a structure is unlocked. Position sizing, risk enforcement, and management triggers never touch an LLM — a check that can hallucinate isn't a check.

Signaldeterministic

Computes IV rank (percentile within a 60-day trailing window), 20-day realized volatility, trend and range scores from price action. Gates whether the LLM even gets called — a quiet scan costs zero tokens.

RegimeLLM

Labels each symbol into one of seven regimes (range/trend × high/low IV, or stress) from a mechanical rule, with latitude for the model to deviate if it states a reason. Falls back to the mechanical label if the LLM is unavailable or malformed — never fabricates a default.

StrategyLLM

Given the regime's permitted structures and a filtered option chain, picks contracts or declines. Every number it returns — width, credit, deltas — is independently recomputed from the chain afterward; the model's own arithmetic is never trusted.

Riskdeterministic

The last gate before any order reaches Alpaca. Eight checks, every one logged whether it passes or fails. Can only reduce exposure — sizes down, vetoes, or halts. Never widens a trade to make it happen.

Entry pipeline

  1. Signal gate. Skip the symbol unless IV rank is available and above 0.35 — a cheap pre-filter that keeps token spend near zero on quiet days.
  2. Regime classification. Cached 30 minutes per symbol; only recomputed when the entry gate passes.
  3. Structure eligibility. The regime unlocks a fixed menu — e.g. range + high IV allows iron condors and credit spreads; range + low IV allows nothing at all (standing down is a normal, expected outcome).
  4. Contract selection. The strategy LLM picks exact strikes from a chain filtered to 7–14 DTE and within 15% of spot, targeting 0.16Δ short legs.
  5. Risk evaluation. All eight checks run regardless of outcome: halt state, defined-risk structure, independently recomputed max loss, position/symbol/cluster caps, daily churn cap, sizing, cash headroom, DTE window.
  6. Price-ladder execution. A limit order steps through three rungs toward the market over 90 seconds. If it still doesn't fill, the order is abandoned — never widened, never chased.

Risk management

Every position is sized to risk a fixed 1% of account equity at most, floored down (never rounded up) to whole contracts. Drawdown is measured continuously against the account's high-water mark:

Max risk per trade1% of equity
Soft drawdown halt (blocks new entries)5% from high-water mark
Hard drawdown halt (flattens everything)10% from high-water mark
Max concurrent positions6
Max positions per underlying1
Equity-beta cluster cap (SPY+QQQ+IWM combined)3
Take-profit50% of credit captured
Stop-loss2× entry credit
Force-close2 DTE, regardless of P/L

A hard drawdown halt is terminal and manual to clear by design — the whole point of a kill switch is that it stays pulled until a human looks at why.

Stack

Alpaca's MCP server is the sole path for orders, positions, and account state — no order is ever placed outside a dedicated execution module, and every one passes the risk check immediately before submission. Market data comes from Alpaca REST directly. Inference runs on Groq's free tier behind a model-agnostic client, so if Groq is unreachable the system degrades to hold-and-manage: existing positions keep being managed by deterministic rules, no new entries open, and nothing silently substitutes a weaker fallback for judgment it can't get.

The full decision trail — every regime label, every strategy construction attempt, every risk veto with its exact reason — is logged to a local SQLite database on the host running the process. This dashboard reads live account and position data directly from Alpaca's API; it doesn't have access to that local decision log, so the running process's own internal halt state isn't reflected here — the "Account Status" shown on the overview page is Alpaca's own account-level status, not vol-desk's internal risk state.