What it does
BetterWheel connects to IB Gateway / TWS, reconciles your live positions into wheel state, and ranks suggestions over live option chains: which put to sell, which covered call to write, when to take profit or roll. You always see a what-if preview and explicitly arm before anything is sent. Offline, it falls back to consistent demo data so it's always usable.
Terminal UI
A ratatui app with a Suggestions tab and a 0DTE tab.
Pure render over app state; key-driven. The original and primary
front-end.
Desktop app
A native Tauri dashboard with inline payoff charts and auto-update. Same guardrailed core, a point-and-click face. Windows & macOS.
Strategy 1 — the wheel
Sell a cash-secured put for premium. If assigned, you own the stock at a discount; write covered calls against it for income until it's called away. Then repeat. BetterWheel automates the selection at every leg and ranks management before new entries, then by annualized yield.
Cash-secured put
The entry. Sell an OTM put, collect premium, stand ready to buy the shares at the strike.
Covered call
Post-assignment income. Write calls against the assigned lot above your cost basis.
Manage
Take-profit and roll. Close winners early; roll threatened legs to keep the wheel turning.
Selling the put
BetterWheel scans each watchlist name's option chain for out-of-the-money puts, filters by moneyness — by delta, or a Black-Scholes delta rebuilt from implied volatility when IBKR reports no greek — and ranks every candidate by annualized return on the cash you'd post as collateral. You take the premium up front; above the strike the put expires worthless and you keep it, below it you're assigned the shares at a price you already chose.
Writing the call
Holding an assigned lot, the covered_call selector
looks for a call to write above your cost basis, so
being called away still books a gain while the premium keeps lowering
that basis. BetterWheel tracks the basis and the running premium
itself — IBKR can't tell you which leg of the wheel a position is on.
Managing what's open
Trades aren't fire-and-forget. The manage selector
proposes take-profit closes — buying a short back
cheap once most of its premium has decayed — and
rolls, closing a threatened leg and reopening it
further out in time or strike to keep the wheel turning instead of
taking a bad assignment.
What's ranked first
Every connected reload yields one ranked list, and
plan() sorts management before new
entries — tending what you already hold beats opening fresh
risk — then by annualized yield. You act from the top; nothing fires
on its own.
Under the hood
The strategy is a pure, broker-agnostic engine/: three
selectors — csp (entry), covered_call
(post-assignment income) and manage (take-profit / roll)
— over plain types, with zero I/O and exhaustive unit tests. A separate
reconciler folds your raw IBKR holdings into wheel state (which symbol
sits at which leg, the share lot, the open short), and a local SQLite
store keeps what the broker doesn't: cost basis, cumulative premium,
pending rolls.
Strategy 2 — 0DTE index structures
A second, separate strategy family: short-dated, defined-risk structures on cash-settled index options (SPX/SPXW). No assignment, no shares — multi-leg combos that live and die intraday. A generic piecewise-linear payoff engine derives risk, reward and breakevens for any leg set. Surfaced on a dedicated 0DTE tab.
- Iron condor
- Sell an out-of-the-money put spread and call spread together; keep both credits as long as price stays between the short strikes. Defined risk on each wing.
- Put / call credit spread
- The one-sided version — sell a single spread on the side you don't expect price to reach. Max profit is the credit; max loss is the width less the credit.
- Broken-wing fly
- A butterfly with unequal wings that skews the risk to one side, often opened for a credit so the other side carries little or no loss.
- Iron fly
- A short straddle wrapped in long wings: a fatter credit than a condor in exchange for a narrow profit zone centred on the strike.
- Short strangle · gated
- A naked short put and call — the only undefined-risk structure here, so it sits behind an extra gate.
Under the hood
Each structure is a pure selector over a both-sides chain that emits a
single OpenStructure { kind, legs } action, and one generic
piecewise-linear payoff engine —
payoff_at, max_loss_per_share,
breakevens — derives the risk, reward and breakevens for
any leg set (that's what draws every payoff curve). Because
SPX/SPXW are cash-settled and European, there's no assignment and no
shares: these live entirely outside the wheel's state machine and go to
market as one guaranteed combo order, priced to IB's $0.05 index tick.
Hands-off — only if you ask
Any 0DTE slot can be set to automate: a 30-second scheduler enters at
your configured time and places a standing profit-close on fill — the
long wings are the stop, so there's no separate stop order.
It's off by default, per slot, still bound by every guardrail, and a
loud ⚡ AUTO-TRADING banner shows whenever a slot is live.
Talking to Interactive Brokers
BetterWheel has no brokerage of its own — it drives your
Interactive Brokers account through IB's local API. You keep IB Gateway
(or TWS) running; BetterWheel connects to it over a socket with the
ibapi Rust crate, reads your positions and the live option
chains, and routes every order back through it. Nothing of yours goes
anywhere but to IB.
What IB Gateway is
A small, headless companion app from Interactive Brokers that holds your authenticated session and exposes the trading API on a local port — the lightweight alternative to the full Trader Workstation (same API, no charts). BetterWheel talks to whichever one you have open.
Paper first, live on purpose
It defaults to the paper port and only goes live when you deliberately switch. Reconnect, timeouts and guardrails behave identically either way — paper is just a different port and a different account.
- Gateway · paper port 4002 — BetterWheel's default
- Gateway · live port 4001
- TWS · paper / live ports 7497 / 7496
- Enable the API in Gateway/TWS settings, with 127.0.0.1 trusted
- Probe it
cargo run --bin spike -- AAPL— a read-only connectivity check
The gotcha worth knowing up front
Connecting isn't the same as getting prices. Even on a paper account, IB returns no option quotes or greeks — so the Suggestions tab stays empty — until you finish the market-data setup in the IBKR client portal: the Market Data API access configuration, the Non-Commercial Form, your subscriber status, and an actual options subscription (OPRA for US options). The app connects fine without it; it just can't rank anything until the data flows. Offline demo mode is unaffected.
Under the hood
All of IB sits behind a single boundary: one module owns the
ibapi client and maps its types into plain structs, every
streaming request is bounded by a timeout, and one
submit_or_preview entry point keeps the what-if and live
order paths from ever diverging. An incomplete snapshot is treated as
unknown, never as "your account is empty," so a dropped
connection can't wipe your wheel state — and if the Gateway isn't
reachable within five seconds at startup, the app falls back to
Black-Scholes-consistent demo data so it's always usable.
Safety model
It is designed so a bug, a typo, or a bad fill can't quietly cost you money.
Paper-first
Defaults to the paper account (port 4002). Live trading is a deliberate switch, not the default.
Three-step transmit gate
Preview (what-if) → arm → execute. A successful live submit auto-disarms immediately.
Guardrails
read_only blocks all transmits; caps on per-order size and total deployed collateral are enforced regardless of what the engine suggests.
0DTE automation is opt-in
Auto-management is off by default, per slot, and still honors every guardrail. A loud banner shows whenever a slot is live.
Get BetterWheel
Free and open source under the AGPL-3.0. Paper-trade it first, read every line if you like, and arm nothing you don't understand.