zfin/TODO.md
Emil Lerch 36d096a938
All checks were successful
Generic zig build / build (push) Successful in 53s
enable ^L to repaint
2026-03-17 09:50:46 -07:00

4.4 KiB

Future Work

Human review of analytics modules

All analytics modules have been human-reviewed:

  • src/analytics/valuation.zig — reviewed
  • src/analytics/risk.zig — reviewed (rewritten: monthly returns, per-period Sharpe, historical T-bill rates)
  • src/analytics/performance.zig — reviewed
  • src/analytics/analysis.zig — reviewed
  • src/analytics/indicators.zig — AI-reviewed only; human review deferred (lower priority)

Provider review

  • src/providers/tiingo.zig — reviewed (new: primary candle provider)
  • src/providers/yahoo.zig — needs human review
  • All other providers — reviewed

CLI/TUI changes

Risk metrics (Sharpe, volatility, max drawdown) now display per trailing period (1Y, 3Y, 5Y, 10Y) in both the TUI performance tab and CLI perf command. CLI portfolio command shows 3-year risk metrics per symbol.

Performance comparison feature idea: compare risk/return metrics of two or more securities side by side. Scope TBD — could focus on stocks/ETFs only. Open question: fixed at 2, or arbitrary N?

TUI issues

Starting the TUI with a ticker symbol doesn't uppercase (why can't we just solve this once?). Display artifacts that don't go away when switching tabs (need specific steps to reproduce).

Risk-free rate maintenance

T-bill rates are hardcoded in src/analytics/risk.zig as a year-by-year table (source: FRED series DTB3). Each trailing period uses the average rate over its date range. The table includes update instructions as doc comments.

Action needed annually: Update the current year's rate mid-year, finalize the prior year's rate in January. See the curl commands in the tbill_rates doc comment.

CLI/TUI code review (lower priority)

No review has been done on these files. They are presentation-layer code and not part of the reusable library API.

TUI:

  • src/tui.zig
  • src/tui/chart.zig
  • src/tui/keybinds.zig
  • src/tui/theme.zig

Commands:

  • src/commands/common.zig
  • src/commands/analysis.zig
  • src/commands/cache.zig
  • src/commands/divs.zig
  • src/commands/earnings.zig
  • src/commands/enrich.zig
  • src/commands/etf.zig
  • src/commands/history.zig
  • src/commands/lookup.zig
  • src/commands/options.zig
  • src/commands/perf.zig
  • src/commands/portfolio.zig
  • src/commands/quote.zig
  • src/commands/splits.zig

Market-aware cache TTL for daily candles

Daily candle TTL is currently 23h45m, but candle data only becomes meaningful after the market close. Investigate keying the cache freshness to ~4:30 PM Eastern rather than a rolling window. This would avoid unnecessary refetches during the trading day and ensure a fetch shortly after close gets fresh data. Probably alleviated by the cron job approach.

Cron timing for mutual fund NAVs

Tiingo publishes mutual fund NAVs after midnight ET. The server cron (currently 8 PM ET weekdays) gets stock/ETF data same-day but mutual fund NAVs lag by one trading day. Consider pushing the cron to midnight ET or adding a second morning run for funds.

On-demand server-side fetch for new symbols

Currently the server's SRF endpoints (/candles, /dividends, etc.) are pure cache reads — they 404 if the data isn't already on disk. New symbols only get populated when added to the portfolio and picked up by the next cron refresh.

Consider: on a cache miss, instead of blocking the HTTP response with a multi-second provider fetch, kick off an async background fetch (or just auto-add the symbol to the portfolio) and return 404 as usual. The next request — or the next cron run — would then have the data. This gives "instant-ish gratification" for new symbols without the downsides of synchronous fetch-on-miss (latency, rate limit contention, unbounded cache growth from arbitrary tickers).

Note that this process doesn't do anything to eliminate all the API keys that are necessary for a fully functioning system. A more aggressive view would be to treat ZFIN_SERVER as a 100% source of record, but that would introduce some opacity to the process as we wait for candles (for example) to populate. This could be solved on the server by spawning a thread to fetch the data, then returning 202 Accepted, which could then be polled client side. Maybe this is a better long term approach?

Server deployment

After committing and pushing changes, rebuild and deploy zfin-server on nas2. The server needs the TIINGO_API_KEY added to /data/zfin/.env on the host.