A Streamlit dashboard for theta and wheel strategy traders on TastyTrade. Built around premium selling — short puts, covered calls, strangles, and the wheel — with metrics that matter for multi-day holds: capture %, annualised return, banked $/day, effective basis, and campaign tracking.
Upload your CSV export and get a full breakdown of realized P/L, wheel campaigns, trade analytics, and portfolio health — all running locally or on Streamlit Community Cloud. Your data is never sent anywhere.
Heads up for 0DTE traders: the app works but some metrics (Ann Return %, Med Premium/Day, Wheel Campaigns) are less meaningful for same-day trades. 0DTE-specific analytics are on the roadmap.
Personal project. TastyMechanics is built around how I trade — wheel strategies, theta harvesting, and premium selling on TastyTrade. It works well for my account and my style. It may not fit yours out of the box, and that is intentional. If you trade differently — 0DTE, futures, spreads-heavy, non-US — the numbers may not tell the full story. You are welcome to fork the repo and customise it to match your trading style. The codebase is modular by design: analytics live in
mechanics.py, display intabs/, constants inconfig.py. Changing a metric or adding a new one is usually a small, contained change.
Hosted on Streamlit Community Cloud — upload your CSV and explore without installing anything:
https://tastymechanics-76dxruw38qjhqc2bdxgfrc.streamlit.app/
Open Positions tab
- Position cards per ticker: strategy badge, DTE progress bar, cost basis per leg
- Live market prices via Yahoo Finance (opt-in toggle) — last price, day change %, mark (bid/ask) for each option leg, unrealised P/L per leg and card total
- Per-share unrealised breakdown on stock legs (e.g.
-$620.08 / -$6.20/sh) - % of premium captured on single-leg short options (e.g.
23% captured) - Spread context row for vertical spreads — net credit/debit, max loss/profit, % of max profit
- Strategy detection covers Iron Condor, Reverse Iron Condor, Iron Butterfly, Reverse Iron Butterfly, Jade Lizard, Big Lizard, Short Strangle, Risk Reversal, vertical spreads, butterflies, calendars, covered structures
- Expiry alert strip — all options expiring within 21 days, colour-coded by urgency
Portfolio Overview
- Realized P/L, Return on Capital, Capital Efficiency Score (annualised)
- Capital deployed, margin loan, dividends + interest
- Inline P/L breakdown chips (campaign type and windowed components)
- Period comparison card — current vs prior equivalent window with deltas
Derivatives Performance tab
- Premium selling scorecard: win rate, median capture %, median days held, annualised return, banked $/day
- Avg winner / loser, win/loss ratio, total fees and fees as % of P/L
- Call vs Put performance table
- Defined vs Undefined Risk breakdown by strategy
- Performance by ticker table
- DTE at open distribution, rolling win rate chart
- Options P/L by week and month (candlestick — shows equity curve OHLC per period)
Discipline & Patterns tab
- ThetaGang scorecard: management rate, median DTE at open/close, top-3 concentration, assignment rate, early management rate
- LEAPS automatically separated from short-premium metrics (DTE > 90 threshold)
- Cumulative P/L equity curve, weekly and monthly candlestick curves
- DTE Discipline section — win rate and avg P/L by DTE at open, close distribution with TastyTrade target zone
- Trade Quality section — win/loss P/L histogram, rolling 10-trade capture % and win rate
- Timing & Concentration — P/L by day of week and hour, ticker × month heatmap
- Best/Worst 5 trades and full closed trade log
Wheel Campaigns tab
- Per-ticker campaign cards: entry basis, effective basis, premiums banked, realised P/L
- "Days to Free" — projected days until effective cost basis reaches $0 at current premium/dividend rate
- Pre-purchase option attribution note when pre-campaign closing debits affect the premium total
- Option roll chain visualisation — calls and puts tracked as separate chains
- Share and dividend event log per campaign
- Lifetime "House Money" mode toggle (in-tab, right of heading)
Portfolio Realized P/L tab
- Full ticker breakdown: premiums, dividends, options P/L, capital deployed
- Stacked cash-flow bar charts by week and month — Options / Equity / Income breakdown
- Volatility metrics: avg week P/L, weekly std dev, Sharpe-equivalent, profitable weeks %, max drawdown + recovery
Deposits, Dividends & Fees tab
- Full income and cash movement log with colour-coded row types
HTML Report Export
- Download button in sidebar generates a self-contained dark-theme HTML file
- Includes: Portfolio Overview scorecard, Options Trading scorecard (credit trades only), equity curve, weekly/monthly candle charts, performance by ticker table
- Reflects the currently selected time window
- No external dependencies — Plotly charts embedded via CDN
python >= 3.10
streamlit >= 1.30
pandas >= 2.0
plotly >= 5.0
yfinance >= 0.2 # optional — only required for live market prices
pip install -r requirements.txtstreamlit run tastymechanics.pyThen open http://localhost:8501 in your browser.
Don't have a TastyTrade account yet? Open one here — this app was built and tested exclusively on TastyTrade exports.
- Log in to TastyTrade
- Go to History → Transactions
- Set your date range — export your full account history, not just a recent window
- Click Download CSV
- Upload the file in the dashboard sidebar
Why full history matters: FIFO cost basis for equity P/L requires all prior buy transactions to be present, even if the shares were purchased years ago. A partial export will produce incorrect basis and P/L figures for any position that has earlier lots outside the selected date range.
- Fork this repository
- Go to share.streamlit.io and sign in with GitHub
- Click New app → select your fork → set main file to
tastymechanics.py - Deploy — no secrets or environment variables required
A standard Python slim image works. Ensure Python 3.10+ is used:
FROM python:3.12-slim
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
EXPOSE 8501
CMD ["streamlit", "run", "tastymechanics.py", "--server.port=8501", "--server.address=0.0.0.0"]Note: Python 3.10 and 3.11 are supported. Python 3.12 is recommended.
This tool is for personal record-keeping only. It is not financial advice.
Known limitations — verify these manually if they apply to your account:
- Covered calls assigned away — if your shares are called away by assignment, verify the campaign closes and P/L records correctly.
- Multiple assignments on the same ticker — each new buy-in starts a new campaign. Blended basis across campaigns is not combined.
- Long options exercised by you — exercising a long call or put into shares is untested. Check the resulting position and cost basis.
- Futures options delivery — cash-settled futures options (/MES, /ZS etc.) are included in P/L totals, but in-the-money expiry into a futures contract is not handled.
- Stock splits — forward and reverse splits are detected and FIFO-adjusted, but TastyTrade-issued post-split option symbols are not stitched to pre-split contracts.
- Spin-offs and zero-cost deliveries — shares received at $0 cost (spin-offs, ACATS transfers) trigger a warning. A sidebar toggle lets you exclude those tickers from all P/L metrics so the inflated basis doesn't distort Realized ROR or Capital Efficiency.
- Mergers and acquisitions — if a held ticker is acquired or merged, the original campaign may be orphaned with no exit recorded and incomplete P/L. Reconcile manually against your broker statement.
- Complex multi-leg structures — PMCC, diagonals, calendars, and ratio spreads may not be classified correctly in the trade log. P/L totals are correct; trade type labels may not be.
- Non-US accounts — built and tested on a US TastyTrade account. CSV format and field differences for other regions are unknown.
P/L figures are cash-flow based (what actually hit your account) and use FIFO cost basis for equity. They do not account for unrealised gains/losses, wash sale rules, or tax adjustments. Always reconcile against your official TastyTrade statements for tax purposes.
The codebase is split into focused modules with a strict one-way dependency chain. No module imports from the one above it.
config.py Constants + COLOURS palette — OPT_TYPES, TRADE_TYPES, thresholds, patterns
models.py Dataclasses — Campaign, AppData, ParsedData
ingestion.py CSV parsing — pure Python, no Streamlit dependency
mechanics.py Analytics engine — FIFO, campaigns, trade classification
ui_components.py Visual helpers — formatters, colour functions, chart layout
market_data.py Live price fetcher — yfinance wrapper, 5-min cache, opt-in only
report.py HTML report export — self-contained, no Streamlit dependency
tabs/ One renderer per tab (tab0–tab5) + landing.py — imported by tastymechanics.py
tastymechanics.py Streamlit wiring — sidebar, cache wrappers, tab orchestration
Data flow
CSV upload
└── load_and_parse(_file_bytes) cached on raw bytes — reruns only on new file
└── build_all_data(_parsed, use_lifetime)
cached on use_lifetime bool only (DataFrame unhashed)
└── window slices recomputed on time window change (fast, uncached)
See the Architecture wiki page for full detail.
v26.7 — Open Position Card Fixes & Iron Condor Detection (2026-04-17)
- Live option marks now work — two silent bugs fixed:
itertuples()was dropping space-containing column names (Expiration Date→_1) so every mark lookup missed; and TastyTrade exports Saturday OCC settlement dates while yfinance uses the Friday last-trading-day, so the chain fetch never matched. Both fixed. - Iron Condor / Reverse Iron Condor / Iron Butterfly / Reverse Iron Butterfly added to the open positions strategy detector. Previously a four-leg condor was misidentified as Jade Lizard (a subset match). These four structures now take priority and mirror the closed-trades classifier.
- Strategy badge fix — vertical call/put spreads (e.g. a bear call credit spread) were showing as
Long Call. Fixed by replacing an incorrectlc > 1guard with proper strike-comparison logic for both call and put spreads. - Open position card improvements — explicit minus sign on negative unrealised P/L (was colour-only); per-share breakdown on stock legs; % of premium captured on single-leg short options; spread context row showing net credit/debit, max loss, and % of max profit.
- Test suite at 311 tests.
v26.6 — Ratio Spread & Ratio Lizard Detection (2026-03-30)
- Three new strategy labels — Call Ratio Spread, Put Ratio Spread, and Ratio Lizard (short put + unequal call spread, e.g. -1 45P / +1 65C / -2 70C). Previously these fell through to 'Call Credit Spread' or 'Jade Lizard'.
- Jade Lizard detection tightened — now requires equal call quantities on both legs. Unequal-quantity call spreads combined with a short put now correctly classify as Ratio Lizard.
- Capital risk for ratio spreads — the extra naked short leg is priced at the highest short strike × 100 minus credit received, reflecting the unbounded exposure.
- Test suite at 307 tests.
v26.5 — AI Review Prompt & Per-Ticker P/L Redesign (2026-03-21)
- AI Review Prompt in the sidebar — generates a structured markdown prompt covering win rate, capture %, DTE discipline, concentration, and strategy mix, ready to paste into any AI chat for a trading review.
- Per-Ticker P/L columns redesigned — Premiums/Divs/Options → Options / Equity / Income. Options now merges in pre-campaign P/L; Equity is a new FIFO gain/loss column (was previously hidden).
- Portfolio Overview UX — metric captions moved to help tooltips, DATA SYNC header replaced with a lighter caption, corporate action warnings collapsed into an expander, period comparison card moved into the Portfolio P/L tab.
- Time window selector labels now visible consistently across all tabs.
- Tab 4 renamed from "All Trades" to "Portfolio P/L".
v26.4 — Wheel "Days to Free", Stacked Cash-Flow Charts & Tab UX (2026-03-14)
- "Days to Free" estimate on Wheel Campaign cards and summary table — projects how many days at the current premium + dividend collection rate until effective cost basis reaches $0. Displays
~450d,✅ Free, or—(no income collected yet). "at current rate" sub-caption flags it as a straight-line projection. - Stacked cash-flow bar charts in the Portfolio Realized P/L tab — weekly and monthly bars now broken into Options (blue), Equity (orange), and Income (green) segments, making it immediately clear which category is driving a positive or negative period.
- Pre-purchase option attribution banner on Wheel Campaign cards — amber info note when closing debits from options opened before the share purchase land inside the campaign window without their opening credits.
- Discipline & Patterns tab reordered for narrative flow: Cumulative P/L moved to top, both DTE charts grouped under one "DTE Discipline" section, Win/Loss Distribution and Rolling Capture % paired side-by-side under "Trade Quality", timing charts and ticker heatmap under "Timing & Concentration".
- Fix: Monthly options equity curve was showing duplicate month labels (e.g. two "Jan 2026") — x-axis ticks now pinned to exact candle positions via
tickvals/ticktext. - Rename: Portfolio Realized P/L tab sections and charts renamed to "Cash Flow" terminology; caption added explaining settlement-date vs closed-trade methodology difference.
v26.3 — Live Prices & UX Polish (2026-03-06)
- Live market prices on Open Positions tab — opt-in toggle fetches equity quotes and option marks from Yahoo Finance (5-min cache). Shows last price, day change %, mark (bid/ask), and unrealised P/L per leg with a card-level total. Nothing is sent until the toggle is enabled.
- Open Positions cards now show share quantity including fractional holdings (e.g. META 0.2 sh)
- Roll chain table column order and labels updated — Date first,
Exp→ Expiry,Cash→ Credit/Debit Rcvd,Days→ Days Held; closing legs show days the position was held open - Landing page extracted to
tabs/landing.pymatching the tab renderer pattern market_data.pyadded — isolated yfinance wrapper with graceful network-error handlingyfinance>=0.2added torequirements.txt
v25.12 — Charts, Report Export & Fixes (2026-03-01)
- Weekly and Monthly P/L bar charts replaced with candlestick charts
- HTML report export — self-contained dark-theme HTML with two scorecard sections, equity curve, candle charts, and performance by ticker table
- Lifetime "House Money" toggle moved into the Wheel Campaigns tab header
- f-string Python 3.10/3.11 compatibility fix;
datetime.utcnow()deprecation fixed - 13-colour
COLOURSpalette — all hardcoded hex removed from UI layer - Test suite expanded to 294 tests (24 sections); two
detect_strategy()false positives fixed
Earlier releases — v25.3 through v25.11 covered the initial modular refactor (mechanics.py, ingestion.py, tabs/, config.py), FIFO engine fixes, stock split handling, LEAPS separation, and test suite build-out. See git log for detail.
AGPL-3.0 — free to use, modify, and distribute. If you run a modified version as a public web service you must open source your changes under the same licence.
TastyMechanics is free and open source. If it's saved you time or helped you trade smarter, a coffee goes a long way toward covering the 5-sigma moves.
