10 KiB
zfin
A financial data library, CLI, and terminal UI written in Zig. Tracks portfolios, analyzes trailing returns, displays options chains, earnings history, and more -- all from the terminal.
Quick start
macOS (Apple Silicon) -- pre-built binary
# Download the latest aarch64-macos binary, make it executable, drop on $PATH
curl -L -o zfin \
https://git.lerch.org/api/packages/lobo/generic/zfin-aarch64-macos/latest/zfin-aarch64-macos
chmod +x zfin
sudo mv zfin /usr/local/bin/ # or anywhere on $PATH
Linux / building from source
# Requires Zig 0.16.0. With mise installed, `mise install` will pick the right
# version from .mise.toml. Otherwise grab Zig 0.16.0 manually.
zig build
# Binary lands at zig-out/bin/zfin
Configure
# Set at least one API key plus your contact email (see "API keys" below).
# The email is required for ETF profiles + `enrich` because SEC EDGAR mandates
# a User-Agent contact.
export TIINGO_API_KEY=your_key
export ZFIN_USER_EMAIL=you@example.com
Use it
zfin perf VTI # trailing returns
zfin quote AAPL # real-time quote
zfin options AAPL # options chains
zfin earnings MSFT # earnings history
zfin portfolio # portfolio summary (reads portfolio.srf)
zfin analysis # portfolio analysis (reads portfolio.srf + metadata.srf)
# Interactive TUI
zfin i # auto-loads portfolio.srf from cwd
zfin i -p portfolio.srf -w watchlist.srf
zfin i -s AAPL # start with a symbol, no portfolio
Building from source requires Zig 0.16.0.
Documentation
Full user documentation lives in docs/ and is built
around the runnable example portfolios in examples/.
- New here? Getting started -- install, configure, and run your first commands.
- Learn the model: Core concepts.
- Do a task (the user manual):
- Look something up (reference):
- CLI commands
- Config files:
portfolio.srf,accounts.srf,metadata.srf,projections.srf, and more - The interactive TUI
- Data providers and API keys
- Understand the why (explanation): caching, data providers, returns, the projection model, FAQ.
Data providers
zfin aggregates data from multiple free-tier APIs, using each for what it does best, with aggressive caching to stay within free-tier limits.
| Data type | Provider | Auth | Free-tier limit | Cache TTL |
|---|---|---|---|---|
| Daily candles (OHLCV) | Tiingo | TIINGO_API_KEY |
1,000 req/day, 50 req/hour | 23h45m |
| Real-time quotes | Yahoo Finance | None required | Unofficial | Never cached |
| Quote fallback | TwelveData | TWELVEDATA_API_KEY |
8 req/min, 800/day | Never cached |
| Dividends | Polygon | POLYGON_API_KEY |
5 req/min | 14 days |
| Splits | Polygon | POLYGON_API_KEY |
5 req/min | 14 days |
| Options chains | CBOE | None required | ~30 req/min (self-imposed) | 1 hour |
| Earnings | FMP | FMP_API_KEY |
250 req/day | 30 days* |
| ETF profiles | SEC EDGAR | ZFIN_USER_EMAIL |
10 req/sec | ~90 days |
| Classification | Wikidata + EDGAR | ZFIN_USER_EMAIL |
No per-day quota | Long-lived |
Not all keys are required; without a given key, that data type is simply unavailable. For per-provider notes, signup links, the full caching/TTL model, and the complete environment-variable list, see Data providers and API keys, Caching and data freshness, and Environment variables.
Architecture
src/
root.zig Library root, exports all public types
format.zig Shared formatters, braille engine, ANSI helpers
config.zig Configuration from env vars / .env files
service.zig DataService: cache-check -> fetch -> cache -> return
models/
candle.zig OHLCV price bars
date.zig Date type with arithmetic, snapping, formatting
dividend.zig Dividend records with type classification
split.zig Stock splits
option.zig Option contracts and chains
earnings.zig Earnings events with surprise calculation
etf_profile.zig ETF profiles with holdings and sectors
portfolio.zig Lots, positions, and portfolio aggregation
classification.zig Classification metadata parser
quote.zig Real-time quote data
providers/
tiingo.zig Tiingo: daily candles (primary), supplementary div/split merge
twelvedata.zig TwelveData: quote fallback
polygon.zig Polygon: dividends, splits (primary, with forward-looking entries)
fmp.zig FMP: earnings (actuals + estimates)
cboe.zig CBOE: options chains (no API key)
Edgar.zig SEC EDGAR: ETF profiles (NPORT-P), mutual-fund ticker map, XBRL company facts
Wikidata.zig Wikidata SPARQL: classification metadata for `enrich`
yahoo.zig Yahoo Finance: quotes (primary), candles (Tiingo fallback)
openfigi.zig OpenFIGI: CUSIP to ticker lookup
xml.zig Vendored XML parser used by Edgar.zig (see "Vendored code")
analytics/
indicators.zig SMA, Bollinger Bands, RSI
performance.zig Trailing returns (as-of-date + month-end)
risk.zig Volatility, Sharpe, drawdown
valuation.zig Portfolio summary, allocations, covered call adjustments
analysis.zig Portfolio analysis engine (breakdowns by class/sector/geo/account/tax)
cache/
store.zig SRF file cache with TTL freshness checks
net/
http.zig HTTP client with retries and server error retry
rate_limiter.zig Token-bucket rate limiter
commands/
common.zig Shared CLI helpers (progress, formatting)
perf.zig Trailing returns command
quote.zig Quote command
... (14 command files)
tui.zig Interactive TUI application
tui/
chart.zig z2d pixel chart renderer (Kitty graphics)
keybinds.zig Configurable keybinding system
theme.zig Configurable color theme
Data files (user-managed, in project root):
portfolio.srf Portfolio lots
metadata.srf Classification metadata for analysis
accounts.srf Account to tax type mapping for analysis
Dependencies
| Dependency | Source | Purpose |
|---|---|---|
| SRF | Git | Cache file format and portfolio/watchlist parsing |
| libvaxis | Git (v0.6.0) | Terminal UI rendering |
| z2d | Git (v0.11.0) | Pixel chart rendering (Kitty graphics protocol) |
Building
Requires Zig 0.16.0. The canonical version is pinned in .mise.toml:
# Recommended: use mise to install the right Zig and ZLS automatically
mise install
# Or, with Zig 0.16.0 already on PATH:
zig build # build the zfin binary
zig build test # run all tests
zig build run -- <args> # build and run
The compiled binary is at zig-out/bin/zfin.
Vendored code
A small amount of third-party source is vendored directly into the
tree (rather than added as a Zig package dependency) where the
upstream is small, stable, and not packaged for build.zig.zon:
| File | Source | Purpose |
|---|---|---|
src/providers/xml.zig |
Snektron/vulkan-zig, via aws-zig | XML DOM parser used by the EDGAR provider for NPORT-P primary documents. |
Each vendored file carries a // VENDORED - see README.md header
identifying its upstream source. When updating, copy the new
upstream verbatim and re-add the header.
License
MIT