ib_0dte

GitHub

基于IBKR API自动执行0DTE信用价差交易,结合EMA交叉与VIX/VXN波动率 regime 筛选策略,支持指数及股票ETF的自动下单。

.claude/skills/ib_0dte/SKILL.md staskh/trading_skills

Trigger Scenarios

需要自动化执行期权价差交易 根据技术指标和波动率过滤寻找交易机会

Install

npx skills add staskh/trading_skills --skill ib_0dte -g -y
More Options

Non-standard path

npx skills add https://github.com/staskh/trading_skills/tree/main/.claude/skills/ib_0dte -g -y

Use without installing

npx skills use staskh/trading_skills@ib_0dte

指定 Agent (Claude Code)

npx skills add staskh/trading_skills --skill ib_0dte -a claude-code -g -y

安装 repo 全部 skill

npx skills add staskh/trading_skills --all -g -y

预览 repo 内 skill

npx skills add staskh/trading_skills --list

SKILL.md

Frontmatter
{
    "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 EMA21bull_put (signal: "EMA-Up")
  4. EMA9 last crossed below EMA21bear_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)
  • --typebear_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 account resolves — automatic on a single-account login, otherwise --account is required. Rather than fall back to an arbitrary default, the run aborts with success: false and an explanatory error when:

  • no account resolved (multi-account login without --account),
  • ExcessLiquidity could not be read for that account, or
  • the cushion is ≤ 0 — no free margin means no new 0DTE spread; free margin first, or pass --budget to override deliberately.

Pass --budget N any time you want a fixed number; it wins over the lookup entirely (including --budget 0, which is honored as a real value, not as "unset").

Executing a trade

--execute places the chosen spread as a single native BAG combo — both legs (or all four, for an iron condor) fill together, so IBKR margins it as one defined-risk spread. The order is a limit at the net credit (BUY the combo at -credit, which only fills at or better than that credit), time-in-force DAY (0DTE), tagged orderRef=ZDTE_<type>_<symbol>_<expiry>, and routed to --account.

Guardrails before an order is sent:

  • The account must resolve (explicit --account, or a sole managed account).
  • --pick must be within the ranked list.
  • The chosen spread's sized max loss must still fit --budget.
  • Duplicate guard — if an active order with the same orderRef (ZDTE_<type>_<symbol>_<expiry>) already rests in the account, the placement is refused (reports the existing order_id). Pass --replace to cancel and re-place it instead. Prevents a second --execute from stacking a duplicate spread.

The connection is read-only unless --execute is passed, so a plain analysis run can never place an order. Confirm the proposal with the user before executing.

Exit bracket (automatic, non-negotiable on --execute)

Every --execute atomically attaches a full OCA exit bracket — you can never end up holding an unmanaged 0DTE position:

  1. The entry combo is placed and the tool waits for it to fill (--fill-timeout).
  2. If it doesn't fill, the entry is cancelled (no position, no risk) and the result reports why — retry with a marketable --limit or during liquid hours.
  3. On fill, three closing orders are placed in one OCA group (whichever fills first cancels the others, server-side):
    • Profit target — a resting limit to buy back at (1 − target) × credit.
    • Stop — a conditional order that buys back when the underlying breaches the stop level.
    • Time exit — a conditional order that flattens at the --time-exit ET time. If bracket placement fails, the position is emergency market-closed immediately.

The profit target naturally captures near-worthless winners well before the timer, so the time exit mainly flattens positions still hovering near breakeven into the close.

The stop trigger is level-anchored on the underlying (robust to option-price noise), taking whichever of these fires first:

  • Short strike--stop-buffer) — the "thesis broken" level.
  • Premium cap (--stop-mult) — the underlying level where the loss reaches mult × credit, computed via Black-Scholes at entry.
  • Short delta (--stop-delta, optional).

Bear call → stops if the index rises; bull put → if it falls; iron condor → two OCA-linked stops (either breach closes the whole condor). The close is a marketable limit capped at the spread width — fills at market but never worse than the defined max loss. A stop reduces the average loss; it does not guarantee the price in a gap, so the budget-capped max loss remains the true floor.

Verifying / repairing stops

uv run python scripts/zero_dte.py --verify-stops --account U1234567          # report
uv run python scripts/zero_dte.py --verify-stops --repair --account U1234567 # auto-fix

Scans open 0DTE option positions per account and buckets them into protected (a resting ZDTE_STOP_… order exists), unprotected, and unrecognized (legs that don't form a recognized spread). With --repair, each unprotected recognized spread gets a strike-level stop (± the symbol's preset buffer) — a safety net that needs no live market data. Run it after entering trades, and periodically, to confirm nothing is naked.

How ranking works

  • Probability of profit (POP) — probability the spread finishes a winner: the underlying stays on the safe side of the short strike(s) at expiration. From the IBKR short-leg delta (POP ≈ 1 − |delta|), BS N(d2) fallback.
  • Expected value (EV) — the expected P&L integrated over a lognormal with realized vol = --rv-ratio × implied (default 0.85). This counts partial losses (breach just past the short is a small loss), not a flat max loss — which fixes the far-OTM bias of the old binary POP×maxP − (1−POP)×maxL. ev_model is echoed (expected_pnl_rv0.85); if a leg has no IV it falls back to the binary formula.
    • Lower --rv-ratio = more credit-hungry (favors richer near-the-cap strikes); 1.0 ≈ fair (EV near zero — don't use). It's an assumption, not a guarantee.

What --rv-ratio 0.85 actually is

It is an unvalidated prior, not a measured quantity. No backtest in this repo established 0.85; it has not been fitted to SPX/NDX 0DTE data, and it should not be read as one.

The idea behind it is real — the volatility risk premium: implied vol tends to print above subsequently realized vol, which is why selling premium has an edge at all. 0.85 says "assume realized comes in 15% under implied". The direction is well documented; this particular number is a round guess at the magnitude.

Why that matters when reading the output:

  • The ratio is the edge. At --rv-ratio 1.0 expected EV goes to roughly zero. So every positive ev_total the tool reports is a restatement of the assumption, not independent evidence that the trade is good. Rank order between candidates is far more trustworthy than the absolute figures.
  • It is least reliable when it matters most. The premium compresses or inverts exactly when realized vol spikes — the sessions where a 0DTE credit spread does its real damage. The EV model has no awareness of regime; pair it with the --gex read and the timing.events warnings rather than trusting it alone.

To see how much of a candidate's EV is the assumption, re-run with --rv-ratio 1.0 and compare. If EV collapses, the edge was the prior.

Treat it as a tunable, and tune it against your own fills — the paper-test report (scripts/report.py) exists for exactly that.

  • --target-delta — pin the short leg(s) to a delta (± 0.05) for direct strike control, e.g. --target-delta 0.15. Still bounded by --delta.
  • Candidates are ranked by total EV, ties broken toward higher POP.

Output

Every run is automatically saved to sandbox/ as timestamped JSON (e.g. NDX_0dte_bear_call_exec_2026-07-10_093015.json), and the path is echoed as saved_to. This gives a durable trade log — including the order.bracket / binding details that TWS alone doesn't reconstruct. No flag needed.

JSON with:

  • underlying_price, expiry, dte, spread_type, budget, asset_type, account
  • budget_source (excess_liquidity / explicit), budget_frac, excess_liquidity — how the budget was arrived at (see Budget sizing)
  • dry_runtrue unless --execute was passed
  • timing — built-in intraday guidance (see Timing & event guidance below)
  • gex — dealer gamma-exposure profile when --gex is passed, else null (see Gamma exposure (GEX) below): regime, net_gex_bn, flip_level, call_wall, put_wall, heaviest_strikes, weight_source, coverage, caveats, and a guidance sub-block
  • best — the top-ranked spread
  • candidates — top-N spreads, each with legs (action, right, strike, bid, ask, mid, delta, iv), net_credit (mid credit, used for max_profit/EV/breakevens), combo_ask_credit (marketable BUY-side of the combo NBBO — the default execution limit; what fills at market), combo_bid_credit (resting BUY bid — best possible credit, rarely fillable), width, pop, contracts, per-contract and total max_profit / max_loss, capital_at_risk, ev_total, breakeven(s), risk_reward, short_delta, and distance_to_short / distance_to_short_pct (spot-to-short-strike cushion). Iron condors report short_call_delta / short_put_delta and call_distance_to_short / put_distance_to_short.
  • picked — the 1-based rank executed (only when --execute)
  • order — the placement result when --execute: order_id, status, filled, remaining, quantity, limit_price (negative = net credit), account, order_ref, entry_status, log (IB's status/error messages for this order — surfaces the reject reason when an entry goes terminal-Cancelled without filling), and bracket (the attached OCA exit bracket: profit_target (limit_debit), stops (each side's trigger / binding level / order_id), and time_exit (cutoff); or {"ok": false, ...} with an emergency_close if bracket placement failed); or {"ok": false, "error": ...} if a guardrail blocked it

Present the top candidates as a table with columns: strikes, credit, POP, short delta, distance-to-short (points and %), max profit, max loss, contracts, EV. Lead with the best pick and state the direction and the price level it needs the underlying to respect (the short strike / breakeven) — the distance-to-short is the cushion before the trade starts losing.

Paper-test report

Aggregate your saved runs into a summary:

uv run python scripts/report.py            # text summary
uv run python scripts/report.py --json     # machine-readable
  • Entries (from sandbox/*_exec_*.json, automatic): trades placed by symbol/type, entry short-delta range, avg POP, capital at risk, and the stop level placed (binding) distribution.
  • Outcomes (from the latest ib_0dte_paper_test_log_*.md you fill in): win rate, avg win/loss, expectancy per trade, max drawdown, and the actual closed-by leg distribution. Realized P&L only exists once a trade resolves, so it comes from the daily log's P&L / Closed by columns — the entry JSON only captures placement.

Watch expectancy, not win rate: a high win rate with one fat loss can still be negative (the report makes that obvious).

Gamma exposure (GEX)

--gex adds a gex block estimating how much gamma market makers hold across the chain, and what their hedging of it does to the tape:

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

Per strike, GEX = gamma × size × 100 × spot² × 0.01 — the dollars of dealer delta that must be re-hedged per 1% move. Net GEX is calls minus puts, on the standard assumption that dealers are long call gamma / short put gamma (customers buy puts and sell calls).

  • regimepositive_gamma: dealers hedge against the move (sell rallies, buy dips), so vol is suppressed and price mean-reverts — the supportive regime for short premium. negative_gamma: they hedge with the move, amplifying it — the regime that runs credit spreads over. neutral_gamma: the book is balanced, no edge either way.
  • flip_level — the spot where net GEX crosses zero, found by re-deriving every strike's gamma across a ±5% spot grid. Above it you're in the suppressive regime, below it the amplifying one. guidance.spot_vs_flip says which side you're on.
  • call_wall / put_wall — the heaviest gamma strikes above and below spot. Dealer hedging tends to defend them, so they act as barriers.
  • guidance.strike_guidance — where to put the short leg: at or beyond the wall (bear call ≥ call wall, bull put ≤ put wall), so the level dealers defend stands between spot and your short strike.
  • Each candidate gets a gex tag (beyond_wall / at_wall / inside_wall per short leg, with distance_to_wall) and a gex_ok boolean. inside_wall means price can reach your short strike without ever contesting the wall.
  • The regime gate: a negative_gamma read downgrades timing.entry_quality one notch (best/good → fair → avoid) and records timing.gex_gate with the original value and the reason. The clock only knows the time of day; the regime knows whether today's hedging damps moves or feeds them.

GEX is advisory only — it never changes strike selection, sizing, or the order path. Surface gex.regime, the walls, and any guidance.warnings alongside the timing block.

Weighting caveat (read this). IBKR's open interest is the prior settlement's — on a 0DTE expiry most of the book is opened the same morning, so OI misses the flow that actually drives today's hedging. auto therefore weights by same-day volume, which sees today's flow but double-counts round-trips and can't tell an opening trade from a closing one. weight_source and caveats in the output state which was used. A GEX number built on the wrong measure can point at the wrong wall entirely — treat it as a regime filter and a strike-placement prior, not as an edge to lean on hard. The dealer long-call/short-put assumption itself fails when customers are the ones buying calls (a squeeze), which inverts the profile.

Timing & event guidance

Every run includes a timing block, computed from the current ET clock:

  • windowpre_market / opening_bell / morning_prime / midday / afternoon / power_hour / after_hours / weekend
  • entry_qualitybest / good / fair / avoid / closed, tailored to the spread type (credit spreads favor mid-morning; iron condors favor the midday lull; the open and the final power hour are avoid)
  • recommendation — one-line plain-English guidance for the current window
  • events — event-risk guidance, with source:
    • source: "nasdaq" (live economic calendar, keyless, via Nasdaq): reports events_today (each with event, time_et, impact, actual/consensus/previous), high_impact_today (FOMC/CPI/PPI/NFP/PCE/GDP/retail/ISM + Fed-chair remarks), and warnings for high-impact and imminent (within ~30 min) releases.
    • source: "static" (fallback when the calendar can't be reached, or --no-events): recurring intraday-window warnings plus a verify_before_trading checklist.
  • Timing is holiday/early-close aware via the NYSE calendar (half-days shift the close and power-hour windows).

Surface this prominently. Before proposing or (especially) executing, state the timing.recommendation and any timing.events.warnings; if entry_quality is avoid or closed, call that out and suggest waiting. Lead with any high-impact event today (e.g. "FOMC at 14:00 ET") — it can gap the index straight through the short strikes.

The live calendar is fetched by default (no API key needed); pass --no-events to skip it. Event data is US macro releases; for stock underlyings also confirm earnings.

Data sourcing

  • Prices and greeks come from IBKR. Leg prices are IBKR bid/ask/last; delta and IV are IBKR model greeks. The skill only does the spread arithmetic (mid, credit, width, max P&L, POP, EV, distances) on top of that data.
  • By default, if IBKR streams no live quotes/greeks (market closed), the skill returns no candidates plus a hint — it will not compute greeks itself.
  • --allow-stale opts into an off-hours fallback: price from yesterday's settlement close and derive IV/delta via Black-Scholes. Flagged as data_delay: "stalled - using yesterday's close". Useful for previews only — those marks are stale, so numbers (especially far-OTM credits) aren't tradeable.

Notes

  • POP and EV are model-implied under standard (lognormal) assumptions — estimates of the odds, not guarantees.
  • A credit spread's max loss is realized if price blows through the long wing; size accordingly. The budget caps that defined max loss, not slippage or gap risk.

Timezone

All timestamps and time-based calculations use America/New_York. JSON output includes generated_at (NY time string) and data_delay.

Version History

  • 9a1bf57 Current 2026-09-22 03:57

Dependencies

  • required trading-skills

Same Skill Collection

.claude/skills/earnings-calendar/SKILL.md
.claude/skills/fundamentals/SKILL.md
.claude/skills/greeks/SKILL.md
.claude/skills/ib-account/SKILL.md
.claude/skills/ib-collar/SKILL.md
.claude/skills/ib-create-consolidated-report/SKILL.md
.claude/skills/ib-find-short-roll/SKILL.md
.claude/skills/ib-option-chain/SKILL.md
.claude/skills/ib-pmcc-advisor/SKILL.md
.claude/skills/ib-portfolio-action-report/SKILL.md
.claude/skills/ib-portfolio/SKILL.md
.claude/skills/ib-report-delta-adjusted-notional-exposure/SKILL.md
.claude/skills/ib-stop-loss/SKILL.md
.claude/skills/ib-trades-history/SKILL.md
.claude/skills/ib-trailing-stop/SKILL.md
.claude/skills/insider-trading/SKILL.md
.claude/skills/markdown-to-pdf/SKILL.md
.claude/skills/news-sentiment/SKILL.md
.claude/skills/option-chain/SKILL.md
.claude/skills/price-history/SKILL.md
.claude/skills/report-stock/SKILL.md
.claude/skills/risk-assessment/SKILL.md
.claude/skills/scanner-bullish/SKILL.md
.claude/skills/scanner-pmcc/SKILL.md
.claude/skills/spread-analysis/SKILL.md
.claude/skills/stock-quote/SKILL.md
.claude/skills/technical-analysis/SKILL.md
.claude/skills/whale-hunting/SKILL.md

Metadata

Files
0
Version
9a1bf57
Hash
5e731502
Indexed
2026-09-22 03:57

Accueil - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-09-22 06:49
浙ICP备14020137号-1