The argument

You are losing money because you are using delayed retail tools against hedge funds running multi-threaded non-linear models. We are giving you the exact data-layer architecture, code frameworks, and risk-modeling mechanics used on institutional trading floors, optimized to run directly on your own personal server for the cost of a couple of cups of coffee a day.

The architecture

This is the standard institutional data pipeline, implemented at a scale one person can afford to run. It is not a simplification of the real thing — it is the same five stages, with the expensive vendor at each stage replaced by something that costs nothing and does the same job at your volume. Every stage below maps to real code in market_data.py.

01 Ingestion

One adapter class per vendor, each returning the same normalised bar. Adding a vendor is one class and nothing downstream changes.

02 Normalisation

Symbol mapping, corporate actions, timezone discipline, and an explicit adjusted/unadjusted distinction that is never implicit.

03 Validation

Bad-tick screens, duplicate and ordering checks, and single-session move limits that catch unadjusted splits before they become a signal.

04 Storage

Point-in-time cache keyed (symbol, source, date) with the retrieval timestamp. This is what lets you answer “what did I know, and when”.

05 Serving

One function the analytics layer calls. It never learns which vendor answered, so a vendor failing is a routing decision rather than an outage.

Why point-in-time storage is the whole game

Fundamentals get revised. Index membership changes. Prices get back-adjusted for splits and dividends. A backtest run against today’s version of history is testing a strategy that had access to information nobody had at the time — and it will look excellent, because it is quietly cheating. Storing the vintage of each number alongside the number is the difference between research and self-deception, and it costs one extra column.

CREATE TABLE bars (
    symbol       TEXT NOT NULL,
    source       TEXT NOT NULL,     -- which vendor said so
    date         TEXT NOT NULL,     -- the session this describes
    open, high, low, close, volume  REAL,
    adjusted     INTEGER NOT NULL,  -- never implicit
    retrieved_at TEXT NOT NULL,     -- when this vintage entered your world
    PRIMARY KEY (symbol, source, date)
);

That is the entire point-in-time store. A decade of daily bars across a few thousand symbols fits comfortably in a SQLite file you can back up by copying it.

What each layer costs

Layer
Institutional
This stack
Our cost
Market data
Terminal seat licence, bundled feed
2,000/mo
Stooq / Tiingo free tier, cached locally after first fetch
End-of-day equity data is a commodity. You are billed for the terminal, not the bytes.
$0
Historical store
Kdb+ / OneTick tick store
1,500/mo
SQLite point-in-time cache, Parquet for anything larger
SQLite handles a decade of daily bars for thousands of symbols in a file you can back up by copying it.
$0
Compute
Grid / dedicated risk cluster
800/mo
One small VPS, or the machine already on your desk
Portfolio risk on a few hundred positions is milliseconds of arithmetic. The cluster exists for scale you do not have.
$6/mo
Risk analytics
MSCI Barra / Axioma / RiskMetrics
1,200/mo
analytics.py in this repository - VaR, CVaR, drawdown, factor attribution, sizing
The mechanics are public and forty years old. What you buy from a vendor is the factor library and the audit trail.
$0
Optimisation
Commercial MIP solver on a cardinality-constrained problem
900/mo
QUBO formulation + simulated annealing, quantum-annealer ready
The same objective a quantum annealer would be handed. Solved classically here, and fast enough at retail portfolio sizes.
$0
Research / AI layer
Internal quant team
internal
Claude API, metered per call
Costed at a few analyses a day. The only line here that scales with use.
$3/mo
This stack $9/mo
$0.30 a day
Legacy equivalent $6,400/mo
Per seat, before data add-ons
Ratio 711×
Cheaper, same mechanics
In coffees 0.06
Per day, at $5.25 each
Floor $0
Free sources only, self-hosted

Institutional figures are order-of-magnitude for a single seat and vary widely by contract. The point is the ratio, not the decimal. The only line that scales with your usage is the AI layer; everything else is fixed and most of it is zero.

Sources on this installation

Tried in this order. Free and keyless sources come first; the synthetic generator is the floor, never a preference. Currently answering: stooq

Local CSV directory $0 Your own files. The escape hatch that means you are never locked in. Set MARKET_DATA_CSV_DIR to enable.
Tiingo $0 (personal) / $10 mo Clean split/dividend-adjusted history. Generous free personal tier. Set TIINGO_API_KEY to enable.
Polygon.io $29 mo Where you go when you outgrow daily bars and need real intraday. Set POLYGON_API_KEY to enable.
Alpha Vantage $0 (free tier) / $50 mo Free tier is rate limited to a handful of calls a minute - the cache absorbs that. Set ALPHAVANTAGE_API_KEY to enable.
Stooq (free daily CSV) $0 Daily OHLCV, no key required. US tickers are suffixed .us.
yfinance (if installed) $0 Unofficial and can break without warning. Fine as a secondary reconciliation source.
Synthetic (offline, deterministic) $0 Simulated data with volatility clustering and fat tails. Clearly labelled everywhere it appears. Never make a real decision on it.

With no key set at all, the application still works end to end on deterministic simulated data — labelled as such everywhere it appears. A fabricated number that announces itself is a teaching tool; one that does not is a liability.

Log in to reconcile sources and inspect your local cache.

Log in

Running it on your own box

Everything on this page runs on one small server. There is no cluster, no message bus, and no vendor terminal in the path.

# One free source, no registration, no key:
#   (nothing to set — Stooq is the default and answers immediately)

# Better history, free personal tier:
export TIINGO_API_KEY=...

# Your own vendor dump or broker export:
export MARKET_DATA_CSV_DIR=/srv/market-data/csv

# The AI layer (optional — every analytic works without it):
export ANTHROPIC_API_KEY=sk-ant-...

gunicorn -w 2 -b 127.0.0.1:5000 app:app

Two workers is enough. Portfolio risk on a few hundred positions is milliseconds of arithmetic — the grid a bank runs exists for a scale you do not have.