SkillAgentSearch skills...

ib_0dte

Find and place the best 0DTE (zero-days-to-expiration) credit spreads from Interactive Brokers. Default execution route is the EMA9/EMA21 + VIX/VXN regime strategy (ema_vix_0dte.py), which auto-selects bull_put or bear_call from a bare EMA cross and skips the trade when the vol index is elevated (VX…

Install / Use

npx skills add staskh/trading_skills --skill ib_0dte

Installs into whichever agent you are using.

About this skill
📄

SKILL.md

Installable skill definition

Quality Score

91/100

Category

Marketing

Supported Platforms

Universal

Tags

Our assessment of ib_0dte

ib_0dte scores 91/100 on our quality scale, 208th of 606 Marketing skills we index (top 35%).

Its SKILL.md is 28 KB long, well organised into 25 sections with 8 code examples: a thorough specification that gives an agent plenty to work with.

It has 369 GitHub stars, a meaningful sign that others use it.

Substance
30/30
Structure
20/20
Description
15/15
Adoption
11/20
Freshness
15/15

Maintenance, license and trust

  • The repository was last updated 17 days ago, so ib_0dte is actively maintained.
  • It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
  • Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.

Safety scan

No issues found

Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands.

Automated pattern scan on 2026-10-05. It catches known dangerous patterns, not every risk — read a skill before letting an agent act on it.

ib_0dte compared with similar skills

All 4 of these similar skills score higher than ib_0dte; compare them before choosing.

SkillScoreStarsUpdatedFormat
ib_0dte (this skill)by staskh9136917d agoSKILL.md
algorithmic-artby anthropics100177.9k12d agoSKILL.md
pptxby anthropics100177.9k12d agoSKILL.md
designby nextlevelbuilder100130.2k13d agoSKILL.md
ui-ux-pro-maxby nextlevelbuilder100130.2k13d agoSKILL.md

Frequently asked questions

How do I install ib_0dte?
Run npx skills add staskh/trading_skills --skill ib_0dte. The install tabs above show the steps for each supported agent.
Which AI agents does ib_0dte work with?
It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
Is ib_0dte safe to use?
Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. It is MIT-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is ib_0dte still maintained?
The repository was last updated 17 days ago, so ib_0dte is actively maintained.

name: ib_0dte description: Find and place the best 0DTE (zero-days-to-expiration) credit spreads from Interactive Brokers. Default execution route is the EMA9/EMA21 + VIX/VXN regime strategy (ema_vix_0dte.py), which auto-selects bull_put or bear_call from a bare EMA cross and skips the trade when the vol index is elevated (VXN ≥ 35 for NDX/QQQ, VIX ≥ 20 otherwise). Optional --rr-gate and --time-gate add red→red and bar-timing confirmation. Supports cash-settled indices (SPX, NDX, RUT, VIX) and any optionable stock/ETF. Manual spread type override is available via zero_dte.py. Requires TWS or IB Gateway running locally. dependencies: ["trading-skills"]

IB 0DTE Credit Spread Finder & Executor

Default execution route: ema_vix_0dte.py — the EMA9/EMA21 + VIX/VXN regime strategy. It reads the 30-min IB bars, checks the vol index (VXN ≥ 35 for NDX/QQQ, VIX ≥ 20 otherwise), and auto-selects bull_put or bear_call from a bare EMA cross (or skips entirely) before delegating to the spread finder. Optional --rr-gate and --time-gate add confirmation. Use this unless the user explicitly requests a manual spread type.

zero_dte.py is the manual override when the user specifies --type bear_call, --type bull_put, or --type iron_condor directly.

Both scripts share the same spread-finding engine (find → propose → execute on --execute) and all the same flags. All data comes from IBKR.

Supports cash-settled indices (SPX, NDX, RUT, VIX, XSP, DJX) — which trade as Index contracts on their home exchange — as well as any optionable stock or ETF.

Prerequisites

TWS or IB Gateway running locally with the API enabled:

  • Paper trading: port 7497 (default)
  • Live trading: port 7496

Index options require the appropriate index-options market-data entitlement (separate from equity/ETF data). Without it, index quotes will not populate.

Instructions

EMA + VIX/VXN Strategy (recommended — fully automatic signal)

The script checks the vol index, reads the 30-min bars, determines bull_put vs bear_call from the EMA9/EMA21 cross, then calls the spread finder automatically. By default it runs a bare EMA cross with no bar-timing or red→red gate, so it can be run at any time of day. Opt into the confirmation gates per run.

# Dry run (propose only, no order placed) — bare EMA cross.
# Budget auto-sizes to 50% of the account's excess liquidity.
uv run python scripts/ema_vix_0dte.py NDX --account U790497 --port 7496

# With both confirmation gates on (original 10:30-ET behavior)
uv run python scripts/ema_vix_0dte.py NDX --account U790497 --port 7496 \
    --rr-gate --time-gate

# Live execution
uv run python scripts/ema_vix_0dte.py NDX --account U790497 --port 7496 --execute

# Explicit budget override (skips the excess-liquidity lookup)
uv run python scripts/ema_vix_0dte.py NDX --budget 50000 --port 7496 \
    --account U790497 --execute

# SPX variant
uv run python scripts/ema_vix_0dte.py SPX --account U790497 --port 7496 --execute

Vol index: NDX/QQQ are gated on VXN (CBOE Nasdaq-100 Volatility Index — the correct vol gauge for a Nasdaq-100 trade); all other symbols on VIX. The default cutoff is per-index — VXN 35, VIX 20 (VXN typically prints several points above VIX for the same regime). The index used is echoed as vol_index in the output; the vix_* fields hold that index's readings.

The gate is dual: both the intraday reading and the prior-day close must sit below the cutoff, since a market recovering from a high-vol close is still fragile. Both come from IB (vix_source: "ib") — one decision is never assembled from two data sources. Without both readings the run stands down rather than guessing (signal: "VOL-UNAVAILABLE").

Signal logic (default — exits early with success: false and a reason on skip):

  1. No vol reading (intraday or prior-day missing) → no trade (signal: "VOL-UNAVAILABLE")
  2. Vol index ≥ cutoff (VXN ≥ 35 for NDX/QQQ, else VIX ≥ 20, either reading) → no trade (signal: "VIX-SKIP")
  3. EMA9 last crossed above EMA21 → bull_put (signal: "EMA-Up")
  4. EMA9 last crossed below EMA21 → bear_call (signal: "EMA-Dn")

Optional confirmation gates (both off by default):

  • --rr-gate — an EMA-down becomes a Bear Call only if today's two most recently closed bars are both red (signal: "EMA-Dn+RR"); otherwise no trade ("EMA-Dn-no-RR"). The confirmation tracks momentum at the moment of the run, so it means the same thing at 10:30 as at 15:00. A bar still in progress cannot confirm anything and is not counted.
  • --time-gate — require today's 9:30 + 10:00 ET bars (run at 10:30 ET or later) and anchor the EMA-cross lookback to the 10:00 ET bar. Without it the lookback anchors to the latest available bar.

Additional flags:

  • --vix-threshold N — override the vol-index cutoff (default: per-index — VXN 35, VIX 20)
  • --target-delta 0.12 — short-leg delta target (default: 0.12, ≈1.5% OTM at VIX<20)
  • All other zero_dte.py flags (--max-width, --gex, --stop-mult, etc.) pass through

Manual spread finder (explicit type)

Optionally confirm a same-day (0DTE) expiry exists first:

uv run python scripts/zero_dte.py SYMBOL --expiries

Then find the best spreads (dry run — proposes only, places nothing):

uv run python scripts/zero_dte.py SYMBOL --type bear_call --budget 2000

Execute the chosen spread (places a live combo order):

uv run python scripts/zero_dte.py SYMBOL --type bear_call --budget 2000 \
    --account U1234567 --execute            # places the best pick
uv run python scripts/zero_dte.py SYMBOL --budget 2000 \
    --account U1234567 --execute --pick 2   # places the 2nd-ranked pick

Arguments

  • SYMBOL — underlying (e.g. SPX, NDX, RUT, VIX, AAPL, SPY)
  • --type — bear_call (default, bearish/neutral), bull_put (bullish/neutral), or iron_condor (neutral)
  • --budget — max capital at risk in dollars. Caps total max loss; position size is floor(budget / max-loss-per-spread). Default: auto-sized from the live account cushion — see Budget sizing below.
  • --budget-frac — fraction of excess liquidity to deploy when auto-sizing (default: 0.5). Ignored when --budget is passed.
  • --account — IBKR account the trade is committed to. Validated against the connection's managed accounts; echoed in the output. Defaults to the sole managed account when the login has exactly one. Required with --execute when the login manages more than one account.
  • --execute — place the chosen spread as a live combo order. Without it (the default), the tool is a dry run: it proposes but places nothing.
  • --pick N — 1-based rank of the candidate to execute (default: 1 = best).
  • --limit — absolute net-credit limit override. Default: the candidate's combo_ask_credit (the marketable BUY-side of the combo NBBO — sum(short-leg bids) − sum(long-leg asks)), which fills at market. Passing a higher credit here (e.g. mid) is likely to sit at the combo bid and not fill.
  • --limit-frac — walk between the combo NBBO's marketable side and its mid: combo_ask + frac × (net_credit − combo_ask). 0 = fully marketable (same as default), 0.5 = midpoint of combo NBBO, 1.0 = mid credit (rarely fills on multi-leg BAG combos). Computed at execution time, so it stays anchored to the fresh pull's combo quote. Ignored if --limit is set. (Note: IB paper often won't fill multi-leg 0DTE index combos at any marketable price — a paper-sim limitation, not a pricing issue.)
  • --replace — if a live order for this symbol/expiry/type already rests, cancel and re-place it (default: refuse as a duplicate).
  • --stop-mult — premium-cap stop: close when the spread reaches this multiple of the credit (default: 2.0 = lose ~1× credit). 0 disables the premium cap.
  • --stop-buffer — points before the short strike to trigger the level stop (default: 0 = at the strike).
  • --stop-delta — also stop when the short-leg delta reaches this level (optional, e.g. 0.30).
  • --profit-target — buy back after capturing this fraction of the credit, e.g. 0.5 = 50% (0 disables). Default: per-symbol preset, else 0.50.
  • --time-exit — flatten remaining spreads at this ET time, e.g. 15:30 (none disables). Default: per-symbol preset, else 15:30.
  • --fill-timeout — seconds to wait for the entry to fill before cancelling it (default: 60). The bracket needs a fill; if the entry doesn't fill it's cancelled so you're never unprotected.
  • --verify-stops — check that every open 0DTE spread has a resting protective stop, then exit (no symbol required). Add --repair to place a strike-level stop on any unprotected position.
  • --repair — with --verify-stops, auto-place a strike-level stop on unprotected positions.

Stop and exit defaults come from per-symbol presets (STOP_PRESETS in zero_dte_stop.py) — each maps mult, buffer, delta, target (profit-take), and time_exit. E.g. NDX uses mult 3.0 + 0.30 delta backstop, 50% target, 15:30 exit; SPX mult 2.5; unlisted symbols mult 2.0. Any explicit flag overrides the preset. Entry short-delta caps are separate (ENTRY_MAX_DELTA: 0.12 index / 0.20 stock). These are starting points; tune them with live data.

  • --expiry YYYYMMDD — override the expiry (default: today ET, i.e. true 0DTE)
  • --top — number of candidates to return (default: 5)
  • --min-pop — minimum probability of profit, 0–1 (default: 0, no filter)
  • --max-width — cap the strike width in dollars (optional)
  • --delta — cap the |delta| of the short leg(s) at entry. Applies to both verticals and (both short legs of) iron condors. Defaults by class: 0.12 for indexes, 0.20 for stocks (ENTRY_MAX_DELTA in zero_dte.py); pass a value here to override. The effective cap is echoed as max_short_delta in the output.
  • --gex — compute the dealer gamma-exposure profile (net GEX, gamma flip, call/put walls), annotate each candidate against the walls, and gate entry_quality on the regime. See Gamma exposure (GEX) below. Costs an extra chain fetch (it pulls both option sides).
  • --gex-weight — size measure behind each strike: volume (today's prints), oi (prior settlement's open interest), or auto (default: volume once it has printed, else OI).
  • --allow-stale — if IBKR streams no live quotes/greeks (off-hours), price legs from yesterday's settlement close and derive greeks via Black-Scholes. Off by default: greeks come only from IBKR, so a closed market returns no candidates (with a hint) rather than stale, model-computed ones.
  • --no-events — skip the live economic-calendar lookup (falls back to static event guidance). The calendar is fetched by default and needs no API key.
  • --expiries — list available expiries and whether today has a 0DTE
  • --port — IB port (default: 7497 paper; use 7496 for live)

Budget sizing (automatic)

When --budget is omitted, capital-at-risk is sized from the account's live margin cushion: the run reads ExcessLiquidity for the resolved account off the connection it already holds and sets

budget = ExcessLiquidity × --budget-frac        (default 0.5)

A defined-risk vertical consumes roughly its max loss in margin, so the budget cap and the margin actually drawn are the same number — deploying the full cushion would leave zero buffer before IB's forced liquidation, which is why the default is half.

The output echoes budget, budget_source (excess_liquidity or explicit), budget_frac, and the excess_liquidity reading it was derived from. Surface the cushion and the derived budget when presenting candidates so the sizing is visible.

The lookup uses the same IB connection as the chain fetch — no second connect, so no client-ID collision.

It needs to know which account. Margin does not cross account boundaries, so the budget can only be sized once an

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars369
CategoryMarketing
Updated17d ago
Forks85

Languages

Python

Trust signals

100/100

From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.

No cautions