Skip to content

calesthio/OptionsCanvas

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

15 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

OptionsCanvas

License: AGPL v3

Stop getting your stops hunted.

You see the setup forming on the SPY chart. You know exactly where you want to enter, exactly where you're wrong, exactly where you'll take profit β€” all in SPY dollars, the chart you actually understand.

Then you tab over to your broker. Pick an expiration. Scroll the strike ladder. Compute how many contracts $1,000 buys. Set the stop in option premium dollars (not the SPY level you actually understand). Submit. Watch a market-maker tap your stop on a wick fifteen seconds after the open.

OptionsCanvas fixes both halves of that.

  • Your stops live locally. Not on the broker order book. Not visible to the HFTs that profit from hunting them. We only send a market order at the moment the underlying actually breaches your level.
  • You never touch the options chain. You drag your entry, SL, and TP directly on the underlying's chart β€” we pick the strike, the DTE, the contract count, and project the option premium and P&L in real time as you drag.

Two-keystroke execution. Runs 100% on your machine. The first open-source options platform that does this.

options-canvas_silent_720p.mp4

Overview


Built for the active options trader who…

  • Trades short-dated options β€” whether that's 0 DTE on SPY or a month out on AAPL β€” directly off the underlying chart
  • Wants to think in underlying price (the chart you actually read), not in option premium
  • Has been stop-hunted one too many times and never wants a resting stop in the broker's book again
  • Refuses to click 7 times to get a trade on
  • Needs hotkeys, flatten-all, and one-gesture brackets β€” not modal dialogs

Works on any optionable US equity or ETF your broker supports β€” index ETFs, single names, leveraged ETFs, whatever. Configure your watchlist and the platform pulls expirations + strike increments straight from the broker.

If that's you, keep reading.


What makes it different

🎯 Your chart is your order ticket

Drag the Buy, SL, and TP pills directly on the underlying chart. No ticket window. No popups. The price line is the control.

  • Drag Buy away from live price β†’ flips into a limit-trigger with an anchored ENTRY line
  • Drag TP or SL up or down β†’ level updates live, projected premium and P&L update with it
Drag SL/TP pills on the underlying chart Drag Buy off live price β€” limit-trigger with anchored ENTRY line
Drag SL/TP on the underlying β€” premium + P&L recompute as you drag. Drag Buy off live price β€” becomes a limit-trigger with an anchored ENTRY line.

πŸ›‘οΈ Stops your broker can't see β€” and can't hunt

Stops and targets do not sit in your broker's order book. They live in your local machine and only become a real market order at the instant the underlying actually breaches your level.

  • No resting stop for HFTs to sweep
  • No "stop tag + reverse" 15 seconds after the open
  • The broker sees a market order after the breach, never before
  • You stop providing free liquidity to the venue
   You set SL @ 449.50
            β”‚
            β–Ό
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚    trading_engine     β”‚   ← stop lives here, in memory + SQLite
  β”‚   holds SL locally    β”‚     (broker never sees it)
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
              β”‚
              β”‚  polls underlying quote
              β–Ό
      underlying ≀ 449.50 ?
              β”‚
              β”‚  yes
              β–Ό
  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚   market SELL fires   β”‚   β†’ broker (first time the
  β”‚       to broker       β”‚     order book sees anything)
  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

🧠 Think in the underlying. Trade in options.

You set levels on the underlying chart (e.g. your ticker at 449.50). OptionsCanvas does the contract math.

  • Auto-picks the contract β€” DTE from your configured presets (0 DTE, weeklies, monthlies β€” whatever you list), ATM strike from the live chain, both pulled fresh from the broker
  • Black-Scholes overlay projects the option premium and your P&L while you drag, so you see "if the underlying hits 451, this call is worth $2.40 and you make $640"
  • Strike increments and expirations come from the broker as source of truth β€” no manual contract config, no stale chains

Side panel: underlying-priced SL/TP, Smart auto-SL button, auto-picked contract and quantity

One screenshot, the whole pitch: SL and TP labeled in underlying dollars (not option premium). One-tap Smart button auto-sets stops from ATR. The contract SPY260526C00746000, the 3-contract size, and the $823.50 cost β€” all computed for you. Hit the big green button, you're in. Hit "Close All Positions", you're flat.

⚑ Speed of execution

Built so a trade is two keystrokes, not seven clicks.

  • B β†’ Buy CALL at market (ATM, auto-sized)
  • S β†’ Buy PUT at market
  • F β†’ Flatten all positions, instantly
  • Shift+B β†’ Bracket draw mode: click entry, drag to TP, release β€” done
  • C β†’ Toggle CALL/PUT β€’ ↑/↓ β†’ strike up/down
  • 1–5 β†’ preset position sizes ($500 / $1k / $2k / $5k / $10k)
  • Alt + 1..6 β†’ 1m / 5m / 15m / 30m / 1h / 1d timeframe
  • Alt + ←/β†’ β†’ previous/next symbol β€’ ? β†’ cheatsheet

🎨 One-gesture bracket orders

Hit Shift+B, click entry, drag to where you want profit. Direction of drag picks CALL vs PUT. Default 2:1 R:R is auto-applied. Release to send. That's the whole interaction.

πŸ€– Smart defaults that aren't dumb

  • ATR-based SL (1.5Γ— ATR-14) reconciled against swing high/low lookback β€” picks the more conservative
  • 2:1 R:R TP by default, override per trade
  • Smart sizing presets so you stop fat-fingering 100 contracts at 3:59pm

πŸ“Š The chart you'd actually use

TradingView Lightweight Charts under the hood. Multi-symbol, multi-timeframe.

  • Indicators: VWAP, SMA, EMA, RSI, Volume β€” toggle per chart
  • Drawing tools: trend lines, rectangles, horizontals
  • Dark theme, 60fps, no garbage
  • Right-click context menu with everything one click away

(The hero image at the top of this page is exactly this β€” chart, indicators, draggable Buy/SL/TP pills, side panel, broker pill, Day P&L β€” all rendered live.)

πŸ”’ Local. Private. Yours.

  • Runs 100% on your machine β€” Flask on 127.0.0.1:5001
  • Your keys live in config/config.json, your state in assisted_trading/state/trading.db
  • Zero telemetry. The only outbound traffic is to your broker.
  • No SaaS, no login, no "free tier", no one watching your levels

🧱 Risk controls that actually fire

  • Per-symbol position caps and max simultaneous positions
  • Configurable trading hours (auto-blocks orders outside the window)
  • Auto-sell on SL breach (toggle off if you prefer manual)
  • Daily trade limits and accept-partial-fill behavior, all in JSON config

πŸ““ Every trade journaled β€” automatically

Stop maintaining your trading journal in a spreadsheet. OptionsCanvas writes every fill, every close, every realized P&L to your local SQLite DB as it happens.

  • Per-trade row β€” option symbol, contracts closed, exit price, exit time, realized P&L
  • Daily aggregate β€” total trades, win/loss count, gross profit/loss, net P&L, largest win/loss
  • Plain SQLite at assisted_trading/state/trading.db β€” query with pandas.read_sql, DuckDB, Datasette, Jupyter, whatever you already use for analysis
  • JSON snapshots under assisted_trading/journal/<date>/trades.json for human-readable review
  • REST endpoint GET /api/journal?start_date=...&end_date=... for building your own dashboards
  • It's your data, on your disk β€” nothing leaves the machine

πŸ”Œ Broker-agnostic by design

Currently two brokers ship out of the box:

  • Alpaca β€” production-tested. The reference implementation used during development.
  • Tradier β€” implementation complete but not yet validated end-to-end against a live Tradier sandbox account. Working through that now β€” see Broker support status below.

The broker layer is an abstract interface (broker_interface.py) with a declarative registry (broker_registry.py) β€” adding IBKR, Tastytrade etc. is one new file in backend/ and one entry in the registry. The wizard UI renders dynamically from the registry, so a new broker shows up without any frontend edits.


Setup

Prereqs: Python 3.10+ (or Docker) and a free paper-trading account from a supported broker β€” Alpaca (recommended) or Tradier (experimental β€” see Broker support status). Both take ~2 minutes to create and don't risk real money.

The whole thing, in 3 steps:

  1. Download β€” grab the latest ZIP (or git clone) and unzip it.

  2. Launch β€” pick whichever is easiest:

    • Windows: double-click OptionsCanvas.bat
    • macOS / Linux: ./optionscanvas.sh (first time: chmod +x optionscanvas.sh)
    • Docker (any OS): docker compose up -d β€” see Docker below

    On the first native run it creates a Python venv and installs deps (~2 min). Subsequent launches are instant.

  3. Follow the wizard β€” your browser opens to the setup wizard:

    • Pick a broker (Alpaca recommended; Tradier supported but not yet end-to-end tested) β†’ paste keys β†’ "Test connection"
    • Pick a trading universe: Recommended 30 (default), Full 110, or your own custom watchlist
    • Click "Start trading"

That's it. The trading UI takes over and you're live on paper money.

The wizard also runs idempotently β€” you can revisit http://localhost:5001/setup later to re-onboard symbols or rotate keys.

Docker

Single command, any OS:

docker compose up -d        # build + start
# open http://localhost:5001/setup
docker compose logs -f      # tail logs
docker compose down         # stop

config/ and assisted_trading/state/ are bind-mounted, so your broker keys and trading DB live in the repo dir and survive container rebuilds.

Power-user / manual setup

If you'd rather skip the launcher and do it by hand:

git clone https://github.com/calesthio/OptionsCanvas.git
cd OptionsCanvas
python -m venv .venv && source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -r requirements.txt
python assisted_trading/run_platform.py             # opens browser to /setup wizard

Or skip the wizard entirely (Alpaca-only path β€” Tradier users should use the wizard):

cp config/config.example.json config/config.json    # then paste your Alpaca keys
python scripts/onboard_symbol.py                    # default: 30 Tier-1 names
python scripts/onboard_symbol.py --all              # full 110-name universe
python scripts/onboard_symbol.py AAPL MSFT NVDA     # custom tickers
python assisted_trading/run_platform.py

The Tier-1 default covers SPY, QQQ, NVDA, TSLA, IWM, the Mag-7, top semis (AMD, MU, INTC, AVGO, SOXL/SOXS), high-flow retail names (PLTR, HOOD, MSTR, COIN, F, AAL), sector ETFs (XLE, XLF), and leveraged QQQ (TQQQ/SQQQ). --all adds 80 more across financials, pharma, energy, consumer, China, vol, and bonds.

Optional β€” browser tests (Playwright):

npm install && npx playwright install chromium

Hotkeys cheatsheet

Key Action
B / S Buy CALL / Buy PUT at market
F Flatten all positions
Shift+B Bracket-draw mode (click entry, drag to TP)
C Toggle CALL ↔ PUT
↑ / ↓ Strike up / down
1–5 Position size: $500 / $1k / $2k / $5k / $10k
Alt + 1..6 1m / 5m / 15m / 30m / 1h / 1d
Alt + ← / β†’ Previous / next symbol
D / T Draw horizontal / trend line
Esc Cancel drawing / bracket mode
? Show full shortcuts modal

Broker support status

Broker Status Notes
Alpaca βœ… Production-tested The reference broker used during development. All flows (validate, chart data, option chains, place/cancel orders, positions, server-side stops) exercised continuously against a paper account.
Tradier πŸ§ͺ Implementation complete, end-to-end testing in progress All BrokerInterface methods implemented against Tradier's documented REST API. Verified against the sandbox endpoint at a unit level (auth, error handling, response parsing) but not yet validated through a full sandbox trading session. Use at your own risk until this row turns green; please file issues if you see anything off.

Adding a new broker requires one file in assisted_trading/backend/<name>_broker.py (implementing BrokerInterface) and one entry in broker_registry.py β€” no frontend or trading-engine edits. Contributions welcome.


Configuration

  • config/config.json β€” broker credentials + paper/live mode + global defaults (gitignored, never commit). Written by the setup wizard; you almost never need to edit it by hand.
  • assisted_trading/config/assisted_trading_config.json β€” enabled symbols, DTE presets, position-size presets, max positions, trading hours, auto-sell, entry-order type
  • Broker accounts β€” free paper accounts at Alpaca or Tradier. Paper and live use separate API keys on both brokers β€” generate the right pair from each broker's API settings page.

Architecture

  • Frontend (vanilla JS) β€” ChartManager owns Lightweight Charts. OrderPanelOnChart renders draggable pills. ChartTradingController bridges chart ↔ side panel. BlackScholesCalculator projects premium + P&L. BracketOrderDrawer handles one-gesture brackets. KeyboardShortcutManager for hotkeys. SmartDefaults for ATR-based SL/TP. The setup wizard (setup.html) renders dynamically from /api/setup/brokers.
  • Backend (Flask + SocketIO) β€” chart_api_server.py exposes REST + WS. trading_engine.py runs the loop: entries, fill monitoring, SL/TP breach checks, with a TTL cache + graceful fallback on transient broker errors. order_manager.py + position_manager_v2.py persist to SQLite. state_machine.py enforces invariants. setup_routes.py powers the first-run wizard.
  • Broker layer β€” broker_interface.py (abstract base) + broker_registry.py (declarative metadata, drives wizard UI) + broker_factory.py (builds instances) + alpaca_broker.py and tradier_broker.py (concrete impls). Add a broker: drop one file in backend/, add one entry in the registry.
  • State β€” SQLite at assisted_trading/state/trading.db, auto-migrates on boot.

More: docs/ARCHITECTURE.md.


Testing

pip install -r requirements-test.txt                 # one-time
pytest -q                                            # ~190 unit + property + integration tests
python assisted_trading/run_platform.py &            # then, in another shell:
npx playwright test tests/browser/chart_trading.spec.js

Screenshots in this README are captured by tests/browser/_screenshots.spec.js against the live app.


Contributing

PRs welcome β€” see CONTRIBUTING.md. Keep changes focused, run the suites, respect the broker abstraction and state machine.


If this is useful to you

A star on the repo genuinely helps β€” it's how other options traders find it. Solo dev project with no marketing budget, so word-of-mouth is all there is. If you end up using OptionsCanvas day-to-day, opening an issue with what's working / not working is even more valuable than a star.


License

AGPL-3.0-or-later. Β© 2026 calesthio. See LICENSE. Plain English: run a modified version as a network service β†’ you must share the modified source. Fork it privately for your own trading β†’ you're fine.

Third-party components and their licenses (TradingView Lightweight Chartsβ„’, Alpaca-py, Flask, Socket.IO, etc.) are catalogued in THIRD_PARTY_NOTICES.md.


Disclaimer

  • Paper trading is the default β€” the setup wizard's mode selector defaults to "Paper" on every supported broker. Live trading is supported (switch the toggle to "Live" in the wizard, or edit config/config.json's broker.mode), but the launcher, server, and trading UI all surface loud warnings (terminal banner, server log, red broker pill, app-wide red border, [LIVE] browser-tab prefix) so you can't end up there by accident.
  • Options trading involves substantial risk of loss. You can lose 100% of premium; in some configurations more.
  • Not financial advice. A tool, not a recommendation. Indicators, projected P&L, defaults β€” none of it is advice.
  • No warranty. Authors and contributors are not liable for losses, missed fills, slippage, broker outages, software bugs, or stops that fail to trigger β€” paper or live.
  • If you don't understand exactly what an order will do before you place it β€” don't place it.

About

Stop getting your stops hunted. SL/TP never touch your broker - only fires when the underlying actually breaches your level. And skip the options chain: drag your levels on the chart, we auto-pick the strike + DTE + contracts. The first open-source platform that does both.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors