add shift-tab keybind
This commit is contained in:
parent
facc233976
commit
b510a86b09
2 changed files with 83 additions and 82 deletions
164
README.md
164
README.md
|
|
@ -33,15 +33,15 @@ zfin aggregates data from multiple free-tier APIs. Each provider is used for the
|
|||
|
||||
### Provider summary
|
||||
|
||||
| Data type | Provider | Auth | Free-tier limit | Cache TTL |
|
||||
|---|---|---|---|---|
|
||||
| Daily candles (OHLCV) | TwelveData | `TWELVEDATA_API_KEY` | 8 req/min, 800/day | 24 hours |
|
||||
| Real-time quotes | TwelveData | `TWELVEDATA_API_KEY` | 8 req/min, 800/day | Never cached |
|
||||
| Dividends | Polygon | `POLYGON_API_KEY` | 5 req/min | 7 days |
|
||||
| Splits | Polygon | `POLYGON_API_KEY` | 5 req/min | 7 days |
|
||||
| Options chains | CBOE | None required | ~30 req/min (self-imposed) | 1 hour |
|
||||
| Earnings | Finnhub | `FINNHUB_API_KEY` | 60 req/min | 24 hours |
|
||||
| ETF profiles | Alpha Vantage | `ALPHAVANTAGE_API_KEY` | 25 req/day | 30 days |
|
||||
| Data type | Provider | Auth | Free-tier limit | Cache TTL |
|
||||
|-----------------------|---------------|------------------------|----------------------------|--------------|
|
||||
| Daily candles (OHLCV) | TwelveData | `TWELVEDATA_API_KEY` | 8 req/min, 800/day | 24 hours |
|
||||
| Real-time quotes | TwelveData | `TWELVEDATA_API_KEY` | 8 req/min, 800/day | Never cached |
|
||||
| Dividends | Polygon | `POLYGON_API_KEY` | 5 req/min | 7 days |
|
||||
| Splits | Polygon | `POLYGON_API_KEY` | 5 req/min | 7 days |
|
||||
| Options chains | CBOE | None required | ~30 req/min (self-imposed) | 1 hour |
|
||||
| Earnings | Finnhub | `FINNHUB_API_KEY` | 60 req/min | 24 hours |
|
||||
| ETF profiles | Alpha Vantage | `ALPHAVANTAGE_API_KEY` | 25 req/day | 30 days |
|
||||
|
||||
### TwelveData
|
||||
|
||||
|
|
@ -102,12 +102,12 @@ The cache directory defaults to `~/.cache/zfin` and can be overridden with `ZFIN
|
|||
|
||||
Not all keys are required. Without a key, the corresponding data simply won't be available:
|
||||
|
||||
| Key | Without it |
|
||||
|---|---|
|
||||
| `TWELVEDATA_API_KEY` | No candles, quotes, or trailing returns |
|
||||
| `POLYGON_API_KEY` | No dividends -- trailing returns show price-only (no total return) |
|
||||
| `FINNHUB_API_KEY` | No earnings data (tab disabled) |
|
||||
| `ALPHAVANTAGE_API_KEY` | No ETF profiles |
|
||||
| Key | Without it |
|
||||
|------------------------|--------------------------------------------------------------------|
|
||||
| `TWELVEDATA_API_KEY` | No candles, quotes, or trailing returns |
|
||||
| `POLYGON_API_KEY` | No dividends -- trailing returns show price-only (no total return) |
|
||||
| `FINNHUB_API_KEY` | No earnings data (tab disabled) |
|
||||
| `ALPHAVANTAGE_API_KEY` | No ETF profiles |
|
||||
|
||||
CBOE options require no API key.
|
||||
|
||||
|
|
@ -121,15 +121,15 @@ Every data fetch follows the same pattern:
|
|||
|
||||
Cache files use [SRF](https://github.com/lobo/srf) (Simple Record Format), a line-oriented key-value format. Freshness is determined by file modification time vs. the TTL for that data type.
|
||||
|
||||
| Data type | TTL | Rationale |
|
||||
|---|---|---|
|
||||
| Daily candles | 24 hours | Only changes once per trading day |
|
||||
| Dividends | 7 days | Declared well in advance |
|
||||
| Splits | 7 days | Rare corporate events |
|
||||
| Options | 1 hour | Prices change continuously during market hours |
|
||||
| Earnings | 24 hours | Quarterly events, estimates update periodically |
|
||||
| ETF profiles | 30 days | Holdings/weights change slowly |
|
||||
| Quotes | Never cached | Intended for live price checks |
|
||||
| Data type | TTL | Rationale |
|
||||
|---------------|--------------|-------------------------------------------------|
|
||||
| Daily candles | 24 hours | Only changes once per trading day |
|
||||
| Dividends | 7 days | Declared well in advance |
|
||||
| Splits | 7 days | Rare corporate events |
|
||||
| Options | 1 hour | Prices change continuously during market hours |
|
||||
| Earnings | 24 hours | Quarterly events, estimates update periodically |
|
||||
| ETF profiles | 30 days | Holdings/weights change slowly |
|
||||
| Quotes | Never cached | Intended for live price checks |
|
||||
|
||||
Manual refresh (`r` / `F5` in TUI) invalidates the cache for the current tab's data before re-fetching.
|
||||
|
||||
|
|
@ -137,13 +137,13 @@ Manual refresh (`r` / `F5` in TUI) invalidates the cache for the current tab's d
|
|||
|
||||
Each provider has a client-side token-bucket rate limiter that prevents exceeding free-tier limits:
|
||||
|
||||
| Provider | Rate limit |
|
||||
|---|---|
|
||||
| TwelveData | 8/minute |
|
||||
| Polygon | 5/minute |
|
||||
| Finnhub | 60/minute |
|
||||
| CBOE | 30/minute |
|
||||
| Alpha Vantage | 25/day |
|
||||
| Provider | Rate limit |
|
||||
|---------------|------------|
|
||||
| TwelveData | 8/minute |
|
||||
| Polygon | 5/minute |
|
||||
| Finnhub | 60/minute |
|
||||
| CBOE | 30/minute |
|
||||
| Alpha Vantage | 25/day |
|
||||
|
||||
The limiter blocks until a token is available, spreading bursts of requests automatically rather than failing with 429 errors.
|
||||
|
||||
|
|
@ -212,33 +212,33 @@ Default keybindings:
|
|||
|
||||
| Key | Action |
|
||||
|---|---|
|
||||
| `q`, `Ctrl+c` | Quit |
|
||||
| `r`, `F5` | Refresh current tab (invalidates cache) |
|
||||
| `R` | Reload portfolio from disk (no network) |
|
||||
| `h`, Left | Previous tab |
|
||||
| `l`, Right, Tab | Next tab |
|
||||
| `1`-`6` | Jump to tab |
|
||||
| `j`, Down | Select next row |
|
||||
| `k`, Up | Select previous row |
|
||||
| `Enter` | Expand/collapse (positions, expirations, calls/puts) |
|
||||
| `s` | Select symbol from portfolio for other tabs |
|
||||
| `/` | Enter symbol search |
|
||||
| `e` | Edit portfolio/watchlist in `$EDITOR` |
|
||||
| `<` | Sort by previous column (portfolio tab) |
|
||||
| `>` | Sort by next column (portfolio tab) |
|
||||
| `o` | Reverse sort direction (portfolio tab) |
|
||||
| `[` | Previous chart timeframe (quote tab) |
|
||||
| `]` | Next chart timeframe (quote tab) |
|
||||
| `c` | Toggle all calls collapsed/expanded (options tab) |
|
||||
| `p` | Toggle all puts collapsed/expanded (options tab) |
|
||||
| `Ctrl+1`-`Ctrl+9` | Set options near-the-money filter to +/- N strikes |
|
||||
| `g` | Scroll to top |
|
||||
| `G` | Scroll to bottom |
|
||||
| `Ctrl+d` | Half-page down |
|
||||
| `Ctrl+u` | Half-page up |
|
||||
| `PageDown` | Page down |
|
||||
| `PageUp` | Page up |
|
||||
| `?` | Help screen |
|
||||
| `q`, `Ctrl+c` | Quit |
|
||||
| `r`, `F5` | Refresh current tab (invalidates cache) |
|
||||
| `R` | Reload portfolio from disk (no network) |
|
||||
| `h`, Left | Previous tab |
|
||||
| `l`, Right, Tab | Next tab |
|
||||
| `1`-`6` | Jump to tab |
|
||||
| `j`, Down | Select next row |
|
||||
| `k`, Up | Select previous row |
|
||||
| `Enter` | Expand/collapse (positions, expirations, calls/puts) |
|
||||
| `s` | Select symbol from portfolio for other tabs |
|
||||
| `/` | Enter symbol search |
|
||||
| `e` | Edit portfolio/watchlist in `$EDITOR` |
|
||||
| `<` | Sort by previous column (portfolio tab) |
|
||||
| `>` | Sort by next column (portfolio tab) |
|
||||
| `o` | Reverse sort direction (portfolio tab) |
|
||||
| `[` | Previous chart timeframe (quote tab) |
|
||||
| `]` | Next chart timeframe (quote tab) |
|
||||
| `c` | Toggle all calls collapsed/expanded (options tab) |
|
||||
| `p` | Toggle all puts collapsed/expanded (options tab) |
|
||||
| `Ctrl+1`-`Ctrl+9` | Set options near-the-money filter to +/- N strikes |
|
||||
| `g` | Scroll to top |
|
||||
| `G` | Scroll to bottom |
|
||||
| `Ctrl+d` | Half-page down |
|
||||
| `Ctrl+u` | Half-page up |
|
||||
| `PageDown` | Page down |
|
||||
| `PageUp` | Page up |
|
||||
| `?` | Help screen |
|
||||
|
||||
Mouse: scroll wheel navigates, left-click selects rows and switches tabs, double-click expands/collapses.
|
||||
|
||||
|
|
@ -295,23 +295,23 @@ security_type::watch,symbol::TSLA
|
|||
|
||||
### Lot fields
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|---|---|---|---|
|
||||
| `symbol` | string | Yes* | Ticker symbol or CUSIP. *Optional for `cash` lots. |
|
||||
| `shares` | number | Yes | Number of shares (or face value for cash/CDs) |
|
||||
| `open_date` | string | Yes** | Purchase date (YYYY-MM-DD). **Not required for cash/watch. |
|
||||
| `open_price` | number | Yes** | Purchase price per share. **Not required for cash/watch. |
|
||||
| `close_date` | string | No | Sale date (null = open lot) |
|
||||
| `close_price` | number | No | Sale price per share |
|
||||
| `security_type` | string | No | `stock` (default), `option`, `cd`, `cash`, `illiquid`, `watch` |
|
||||
| `account` | string | No | Account name (e.g. "Roth IRA", "Brokerage") |
|
||||
| `note` | string | No | Descriptive note (shown in cash/CD/illiquid tables) |
|
||||
| `ticker` | string | No | Ticker alias for price fetching (overrides `symbol` for API calls) |
|
||||
| `price` | number | No | Manual price override (fallback when API has no coverage) |
|
||||
| `price_date` | string | No | Date of the manual price (YYYY-MM-DD, for staleness display) |
|
||||
| `drip` | string | No | `true` if lot is from dividend reinvestment (summarized as ST/LT groups) |
|
||||
| `maturity_date` | string | No | CD maturity date (YYYY-MM-DD) |
|
||||
| `rate` | number | No | Interest rate for CDs (e.g. 5.25 = 5.25%) |
|
||||
| Field | Type | Required | Description |
|
||||
|-----------------|--------|----------|--------------------------------------------------------------------------|
|
||||
| `symbol` | string | Yes* | Ticker symbol or CUSIP. *Optional for `cash` lots. |
|
||||
| `shares` | number | Yes | Number of shares (or face value for cash/CDs) |
|
||||
| `open_date` | string | Yes** | Purchase date (YYYY-MM-DD). **Not required for cash/watch. |
|
||||
| `open_price` | number | Yes** | Purchase price per share. **Not required for cash/watch. |
|
||||
| `close_date` | string | No | Sale date (null = open lot) |
|
||||
| `close_price` | number | No | Sale price per share |
|
||||
| `security_type` | string | No | `stock` (default), `option`, `cd`, `cash`, `illiquid`, `watch` |
|
||||
| `account` | string | No | Account name (e.g. "Roth IRA", "Brokerage") |
|
||||
| `note` | string | No | Descriptive note (shown in cash/CD/illiquid tables) |
|
||||
| `ticker` | string | No | Ticker alias for price fetching (overrides `symbol` for API calls) |
|
||||
| `price` | number | No | Manual price override (fallback when API has no coverage) |
|
||||
| `price_date` | string | No | Date of the manual price (YYYY-MM-DD, for staleness display) |
|
||||
| `drip` | string | No | `true` if lot is from dividend reinvestment (summarized as ST/LT groups) |
|
||||
| `maturity_date` | string | No | CD maturity date (YYYY-MM-DD) |
|
||||
| `rate` | number | No | Interest rate for CDs (e.g. 5.25 = 5.25%) |
|
||||
|
||||
### Security types
|
||||
|
||||
|
|
@ -385,13 +385,13 @@ symbol::ARCC,sector::Financials,geo::US,asset_class::US Large Cap
|
|||
|
||||
### Classification fields
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|---|---|---|---|
|
||||
| `symbol` | string | Yes | Ticker symbol or CUSIP (must match `symbol::` or `ticker::` in portfolio) |
|
||||
| `asset_class` | string | No | e.g. "US Large Cap", "Bonds", "Cash & CDs", "Emerging Markets" |
|
||||
| `sector` | string | No | e.g. "Technology", "Healthcare", "Financials" |
|
||||
| `geo` | string | No | e.g. "US", "International Developed", "Emerging Markets" |
|
||||
| `pct` | number | No | Percentage weight for this entry (default 100). Use for blended funds. |
|
||||
| Field | Type | Required | Description |
|
||||
|---------------|--------|----------|---------------------------------------------------------------------------|
|
||||
| `symbol` | string | Yes | Ticker symbol or CUSIP (must match `symbol::` or `ticker::` in portfolio) |
|
||||
| `asset_class` | string | No | e.g. "US Large Cap", "Bonds", "Cash & CDs", "Emerging Markets" |
|
||||
| `sector` | string | No | e.g. "Technology", "Healthcare", "Financials" |
|
||||
| `geo` | string | No | e.g. "US", "International Developed", "Emerging Markets" |
|
||||
| `pct` | number | No | Percentage weight for this entry (default 100). Use for blended funds. |
|
||||
|
||||
For single-asset-class securities (individual stocks, single-focus ETFs), one line at the default 100% is sufficient. For multi-asset-class funds (target date, balanced), add multiple lines for the same symbol with `pct:num:` values that sum to approximately 100.
|
||||
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ const default_bindings = [_]Binding{
|
|||
.{ .action = .refresh, .key = .{ .codepoint = vaxis.Key.f5 } },
|
||||
.{ .action = .prev_tab, .key = .{ .codepoint = 'h' } },
|
||||
.{ .action = .prev_tab, .key = .{ .codepoint = vaxis.Key.left } },
|
||||
.{ .action = .prev_tab, .key = .{ .codepoint = vaxis.Key.tab, .mods = .{ .shift = true } } },
|
||||
.{ .action = .next_tab, .key = .{ .codepoint = 'l' } },
|
||||
.{ .action = .next_tab, .key = .{ .codepoint = vaxis.Key.right } },
|
||||
.{ .action = .next_tab, .key = .{ .codepoint = vaxis.Key.tab } },
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue