Skip to content

madpin/etorotui

Repository files navigation

etorotui

A copy-trading–first Terminal UI for analysing personal investments on eToro.

Built with Textual, backed by local SQLite history.

Status: v0.1 — all three phases from PRD.md implemented + UX polish pass.

Dashboard

A guided tour of every panel — with screenshots and what-the-keys-do — lives in docs/USAGE.md. All screenshots in this README and in the manual are produced from synthetic data via scripts/generate_screenshots.py; no real account numbers leak into the repo.


What it does

A multi-panel TUI with 20 tabbed panels plus 4 drill-down panels grouped into 8 categories (Overview / Portfolio / Performance / History / Risk / Discover / Notes / Plan):

Phase 1 — MVP

  • Summary — persistent header with equity, cash, invested, P&L, delta arrows, and a 30-snapshot trend sparkline.
  • Dashboard (new) — at-a-glance landing page: KPIs, trend, top 5 winners / losers, top exposures, recent activity.
  • Stocks — open self-managed positions, sortable, filterable, Enter drills into the instrument.
  • Mirrors — copy-trading dashboard with compound monthly return per trader.
  • Monthly — month-by-month gain %, cumulative compounded, realized $ split (stocks vs copies).
  • Look-throughthe product differentiator: aggregates positions across every copy + self-managed into one virtual portfolio per ticker ("what am I actually exposed to?").
  • Equity Curve — line of local equity history + monthly gain bars, with drawdown overlay.
  • Instrument Detail — open lots (self + via-mirror), closed trades, win rate.
  • Mirror Detail — trader's monthly history + your current holdings via them.
  • Settings & Help — editable config, live keybinding map.

Phase 2 — Analytics & Discovery

  • Trade History — paginated closed trades with category (self/copy) and win-rate stats.
  • Allocation — by industry, asset class, and the stock-vs-copy ratio.
  • Copy Risk — per-mirror concentration flag (HIGH/ELEVATED/OK).
  • Mirror Compare — months × traders heatmap of monthly gain %.
  • Trader Scout — search /user-info/people/search by period + filters; save candidates locally.
  • Trader Profile — drill-down from Trader Scout with public metrics, monthly gain, and visible holdings.
  • Watchlists — saved candidates + eToro-native watchlists (fetch on demand).
  • Heatmap — calendar-style daily P&L grid.
  • Journal — timestamped notes per instrument/mirror/global.
  • Alerts — local rules engine (concentration, mirror drawdown, position drawdown) evaluated on every refresh.

Phase 3 — Attribution & Planning

  • Attribution — splits realized returns into stocks vs copies per month, with a winner column.
  • Sector Allocation Detail — per-sector P&L and return %.
  • Cash & Orders — cash breakdown plus pending orders table.
  • What-if — project months-to-target based on local equity curve's avg-monthly trend.
  • Candle Chart — OHLC sub-pane launched from Instrument Detail via c (1D / 1h / 1W toggles).

Cross-cutting

  • Manual refresh (r) — fetches portfolio, P&L, trade history, and monthly gain concurrently.
  • Every refresh persists to SQLite → enables equity curves, drawdowns, and longitudinal analytics.
  • Read-only: trading actions exist as placeholders that always raise TradingDisabledError.
  • Mouse + keyboard (vim-style hjkl, arrows, and number hotkeys).
  • Discoverability: tabs are prefixed with [N] numeric hotkeys + a category icon; a contextual status bar between the panel and the footer always shows the current panel's hint and panel-specific keys; the command palette groups all 20 panels by category for fuzzy search.

See PRD.md for the full spec, schema, and panel specifications.


Screenshots

Selected panels — see docs/USAGE.md for the full tour.

Stocks — open self-managed positions Mirrors — copy-trading dashboard
Stocks Mirrors
Look-through — real exposure across self + every copy Monthly — gain %, cumulative compound, $ split
Look-through Monthly
Equity Curve — local history + drawdown overlay Heatmap — daily P&L calendar grid
Equity Curve Heatmap
Copy Risk — concentration + riskScore + drawdown Mirror Compare — months × traders heatmap
Copy Risk Mirror Compare
Trade History — every closed trade, stocks vs copy Help overlay — live keybindings + panel map
Trade History Help

Requirements

  • Python 3.12+
  • An eToro account with API access enabled
    • Generate keys at: eToro → Settings → Trading → API Key Management
    • Choose Real environment and Read permission for MVP

Quick start

git clone https://github.com/madpin/etorotui.git
cd etorotui

# 1. venv + install
uv venv
source .venv/bin/activate
uv pip install -e ".[dev]"

# 2. credentials
cp .env.example .env
# edit .env and paste ETORO_API_KEY and ETORO_USER_KEY

# 3. config (optional)
cp etorotui.toml.example etorotui.toml
# edit etorotui.toml to taste

# 4. run
etorotui                  # real account
etorotui --mode demo      # demo account
uv run etorotui           # alternative

Key bindings (defaults)

Key Action
r Refresh snapshot
: Command palette — type to jump to any panel or action
t Toggle theme (dark / light)
19 Jump to the Nth tab (titles are numbered for clarity)
Tab / Shift+Tab Next / previous panel
Enter Drill into selected row
Esc / Backspace Back from drill-down / close filter
s / Shift+S Cycle sort column / reverse (arrows in header show direction)
/ Filter rows (live substring match + row counter)
j Journal note (selected row)
? / F1 Categorized help overlay
Ctrl+, Settings
q / Ctrl+C Quit

All keys are remappable in etorotui.toml[keybindings].


Configuration

./etorotui.toml — see etorotui.toml.example for an annotated reference. Highlights:

  • [ui].themedark (default) or light
  • [ui].default_months — window for Monthly P&L panel
  • [ui.layout].panels — order of panels in the main screen
  • [history].db_path — where SQLite snapshots are stored
  • [features].trading — must remain false in MVP
  • [keybindings] — remap any default key

Development

ruff check .       # lint (clean)
ruff format .      # format
pytest -q          # 71 tests, all passing

Coding rules and architecture: AGENTS.md. Per-area conventions in .cursor/rules/.

Tests

The test suite is grounded in a redacted snapshot of a real account (tests/fixtures/etoro_snapshot.json — username/CIDs zeroed out). Aggregation math and SQLite round-trips are verified against this fixture.

pytest -q
# ======================== 71 passed in 0.9s =========================

Regenerating screenshots

source .venv/bin/activate
python scripts/generate_screenshots.py     # writes docs/screenshots/*.svg

The script builds a fully synthetic SnapshotView, populates a throwaway SQLite database with ~30 historical snapshots, and drives the Textual app via App.run_test(...) to capture SVGs. No credentials, no network calls, no real account data — the constants at the top of the script are the entire fixture.


Project layout

src/etorotui/
  cli.py app.py config.py theme.tcss
  api/        # async eToro client + pydantic models
  services/   # portfolio, mirrors, market, history
  db/         # schema.sql, migrations, repository
  ui/
    screens/  # main, detail, settings, help
    panels/   # one file per panel
    widgets/  # pnl_cell, sparkline, sortable_table, toast
  actions/    # placeholder for future trading actions
  utils/      # format/math helpers
tests/        # JSON-fixture-based smoke tests

Acknowledgements

  • Aggregation math and rendering helpers are ported from a working single-file Rich script (portfolio.py) — the predecessor to this project.
  • eToro Public API documentation: https://api-portal.etoro.com/.

License

See LICENSE.

About

Etoro Terminal UI

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages