finance web server
Find a file
2026-03-10 17:29:33 -07:00
src ai all the things 2026-03-10 17:29:33 -07:00
.gitignore add basic structure 2026-03-10 17:29:14 -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 ai all the things 2026-03-10 17:29:33 -07:00
build.zig.zon ai all the things 2026-03-10 17:29:33 -07:00
LICENSE add basic structure 2026-03-10 17:29:14 -07:00
portfolio.srf ai all the things 2026-03-10 17:29:33 -07:00
README.md ai all the things 2026-03-10 17:29:33 -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 nightly at 5pm ET (after market close)
0 17 * * 1-5 cd /path/to/workdir && ZFIN_PORTFOLIO=portfolio.srf zfin-server refresh

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