finance web server
Find a file
Emil Lerch 2503f6bc2a
Some checks failed
Generic zig build / build (push) Failing after 28s
Generic zig build / deploy (push) Has been skipped
mutual fund logic in zfin proper now
2026-03-11 11:47:29 -07:00
.forgejo/workflows ai: yolo the CI and docker image create/push 2026-03-10 17:48:07 -07:00
docker mutual fund logic in zfin proper now 2026-03-11 11:47:29 -07:00
src mutual fund logic in zfin proper now 2026-03-11 11:47:29 -07:00
.gitignore remove portfolio.srf from repo (probably no biggie, but still) 2026-03-11 08:50:00 -07:00
.mise.toml add basic structure 2026-03-10 17:29:14 -07:00
.pre-commit-config.yaml add basic structure 2026-03-10 17:29:14 -07:00
build.zig main.zig cleanup / add version and rate limiting output 2026-03-11 10:45:48 -07:00
build.zig.zon mutual fund logic in zfin proper now 2026-03-11 11:47:29 -07:00
LICENSE add basic structure 2026-03-10 17:29:14 -07:00
README.md mutual fund logic in zfin proper now 2026-03-11 11:47:29 -07:00

zfin-server

HTTP data service backed by zfin's financial data providers. Serves cached market data over HTTP for two consumers:

  1. LibreCalc spreadsheets — trailing returns via WEBSERVICE/FILTERXML
  2. zfin CLI/TUI — raw SRF cache files as an L1 data cache

Quick start

# Set API keys (same as zfin)
export TWELVEDATA_API_KEY=...
export POLYGON_API_KEY=...

# Start the server
zig build run -- serve --port=8080

# In another terminal
curl http://localhost:8080/AAPL/returns
curl http://localhost:8080/AAPL/returns?fmt=xml

Endpoints

Route Content-Type Description
GET / text/html Landing page
GET /help text/plain Endpoint documentation
GET /symbols application/json List of tracked symbols
GET /:symbol/returns application/json Trailing 1/3/5/10yr returns + volatility
GET /:symbol/returns?fmt=xml application/xml Same, XML for LibreCalc
GET /:symbol/quote application/json Latest quote
GET /:symbol/candles application/x-srf Raw SRF cache file
GET /:symbol/dividends application/x-srf Raw SRF cache file
GET /:symbol/earnings application/x-srf Raw SRF cache file
GET /:symbol/options application/x-srf Raw SRF cache file

LibreCalc usage

=FILTERXML(WEBSERVICE("http://localhost:8080/AAPL/returns?fmt=xml"), "//trailing1YearReturn")

XML response format:

<returns>
  <ticker>AAPL</ticker>
  <returnDate>2026-03-07</returnDate>
  <trailing1YearReturn>12.34000</trailing1YearReturn>
  <trailing3YearReturn>8.56000</trailing3YearReturn>
  <trailing5YearReturn>15.78000</trailing5YearReturn>
  <trailing10YearReturn>22.10000</trailing10YearReturn>
  <volatility>18.50000</volatility>
</returns>

Cache refresh

Use cron to keep the cache warm for all symbols in your portfolio:

# Refresh all portfolio symbols daily at 5pm ET (after market close)
0 17 * * 1-5 cd /path/to/workdir && ZFIN_PORTFOLIO=portfolio.srf zfin-server refresh

The candle cache TTL is 23h45m (not a full 24h), providing a 15-minute jitter buffer so daily cron runs at the same time always see stale data and trigger a fresh fetch. Dividend and earnings TTLs are 14 and 30 days respectively.

The refresh command reads the portfolio SRF file (defaults to portfolio.srf in the current directory if ZFIN_PORTFOLIO is not set), extracts all stock and watch symbols, and fetches candles, dividends, and earnings for each.

Building

Requires Zig 0.15.2.

zig build        # build
zig build test   # run tests
zig build run -- serve --port=8080

Configuration

All configuration is via environment variables:

Variable Required Description
TWELVEDATA_API_KEY Yes TwelveData API key
POLYGON_API_KEY No Polygon API key
FINNHUB_API_KEY No Finnhub API key
ALPHAVANTAGE_API_KEY No Alpha Vantage API key
ZFIN_PORTFOLIO No Path to portfolio SRF (default: portfolio.srf)
ZFIN_CACHE_DIR No Cache directory (default: ~/.cache/zfin)

License

MIT