Skip to main content

ETF research and portfolio analytics terminal

Project description

etfray

CI Docs PyPI License: MIT

A terminal-based ETF research and portfolio analytics application built with Textual.

etfray converts SEC fund filings and IBKR portfolio data into holdings, exposure, concentration, margin, and risk workflows — all from your terminal.

Why etfray?

  • No cloud accounts — No sign-ups, no API keys to manage, no third-party dashboards. Your data stays on your machine.
  • No subscriptions — ETF holdings data comes directly from SEC EDGAR filings. Free, authoritative, and always available.
  • Offline-capable — All data is cached locally in SQLite. After the first fetch, everything works without a network connection.
  • Keyboard-first — Designed for speed. Command palette, tree navigation, and keybindings — no mouse required.

Features

  • ETF Research — Search ETFs, view holdings, sector/geographic exposure, concentration, fees, risk metrics, and SEC documents via EDGAR
  • Portfolio Analytics — Connect to IBKR TWS/Gateway for live positions, lookthrough exposure, concentration analysis, and margin/leverage monitoring
  • Side-by-side Compare — Compare multiple ETFs across holdings, exposure, and fees in a single view
  • Export — Save any view to CSV or JSON for further analysis
  • Keyboard-first — Full TUI with command palette, tree navigation, and keybindings
  • Local & private — All data cached locally in SQLite; no cloud accounts required

Key Capabilities

Capability Details
ETF coverage 10,000+ ETFs via SEC EDGAR N-PORT filings
Data sources EDGAR (official), alternative web scraper, IBKR TWS
Holdings analysis Full position-level breakdown with weight, value, shares
Exposure Sector and geographic exposure from underlying holdings
Concentration Top-N analysis (top 10, 25, 50) with cumulative weight
Portfolio Real-time positions, lookthrough exposure, margin & leverage
Storage Local SQLite — no cloud, no external databases
Freshness Configurable staleness thresholds (default: 30 days fresh, 90 days acceptable)

Usage Examples

Research an ETF

  1. Launch etfray and navigate to Research → Search in the sidebar
  2. Press ctrl+p to open the command palette, type a ticker (e.g., VTI)
  3. Browse tabs: HoldingsExposureConcentrationRisk
  4. Click the Export button to save the current view to CSV

Monitor your portfolio

  1. Ensure IBKR TWS/Gateway is running with API enabled on port 7497
  2. Navigate to Portfolio → Positions in the sidebar
  3. etfray connects lazily — positions load automatically on first access
  4. Switch to Lookthrough to see aggregated exposure across all your ETF holdings
  5. Check Margin for leverage ratio and margin cushion warnings

Architecture

graph LR
    A[SEC EDGAR API] --> C[Data Services]
    B[Web Scraper] --> C
    D[IBKR TWS API] --> C
    C --> E[(SQLite Cache)]
    E --> F[Domain Analytics]
    F --> G[Textual TUI]

Design principles:

  • Local-first — All data cached in SQLite. Works offline after initial fetch.
  • Source provenance — Every data point tracks its origin and fetch date so you know how fresh it is.
  • Lazy connection — IBKR connects only when portfolio views are accessed, not at startup.
  • Separation of concernsdata/ handles I/O, domain/ handles computation, ui/ handles presentation.

Configuration

All settings are managed via Workspace → Settings in the sidebar and stored in ~/.etfray/data.db.

Setting Default Description
ibkr_port 7497 IBKR TWS/Gateway API port
edgar_identity (empty) Your email — required by SEC fair use policy
data_source auto Holdings source: auto, edgar, or web
freshness_days_fresh 30 Days before cached data is considered stale
margin_warning_cushion 0.15 Margin cushion threshold for warnings

See the full configuration reference for all options.

Installation

pip install etfray

Requires Python 3.11+.

Quick Start

etfray

Use the sidebar tree to navigate between Research and Portfolio workspaces. Press ctrl+p to open the command palette.

IBKR Connection

To use portfolio analytics, you need IBKR TWS or IB Gateway running with API connections enabled (default port 7497).

Configure the connection in Workspace → Settings in the sidebar.

Documentation

Full documentation at etfray.readthedocs.io:

Development

git clone https://github.com/alwank/etfray.git
cd etfray
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev,docs]"
pytest

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

etfray-0.1.0.tar.gz (129.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

etfray-0.1.0-py3-none-any.whl (57.6 kB view details)

Uploaded Python 3

File details

Details for the file etfray-0.1.0.tar.gz.

File metadata

  • Download URL: etfray-0.1.0.tar.gz
  • Upload date:
  • Size: 129.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for etfray-0.1.0.tar.gz
Algorithm Hash digest
SHA256 037116b7c1f4f18337e71acd20d13e0d116de190b71a4d7e3e3a3d65c207065a
MD5 7143392d8b9427ce1193ab33cab15f61
BLAKE2b-256 1125d2c11163ad90c8285d7ff223ddd4e7af7e768d0c21caa7f5601712273047

See more details on using hashes here.

Provenance

The following attestation bundles were made for etfray-0.1.0.tar.gz:

Publisher: publish.yml on alwank/etfray

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file etfray-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: etfray-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 57.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for etfray-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 48a687af921ad9b90347c0d08a767234757f627bdb5a5847327016a2edc8910d
MD5 7356ffeff107364a15d2aa8300ec84a1
BLAKE2b-256 e3145118d8176ee4f856122af3eccf2e5277ef9dbae434f18dfafe20bafb57c5

See more details on using hashes here.

Provenance

The following attestation bundles were made for etfray-0.1.0-py3-none-any.whl:

Publisher: publish.yml on alwank/etfray

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page