A model that keeps score
Most analytics stacks end at "show the number". StockLens is organised around what happens next: every claim is committed, checked against what happened, and fed back.
Pure engines
analytics, quant, research, forecast and evidence are pure Python over plain dataclasses: no I/O, no framework, no NumPy. One report object is shared by the page, the agent and the evaluator.
Append-only state
Snapshots, the forecast ledger and agent runs are append-only. A forecast is written before its outcome exists and resolved exactly once.
Tested on noise
Each estimator is tested on a seeded random walk, where it must find nothing, and on a planted signal, where it must find it.
Secure by default
Strict CSP, token-bucket limits, constant-time API keys, ticker allowlist before any upstream URL, non-root read-only container, default-deny egress.
Anatomy of /api/v1/symbols/{symbol}/report
One object, computed in a single pass, read by the page, the AI analyst and the evaluation harness alike. Click a section to see its example.
Select a section
The analyst's tools
Every tool is read-only, takes no symbol, URL or free-form query, and is bound server-side to one report. The terminal submit_report is re-validated and every cited figure is checked against what these tools returned.
Run it locally in a minute
No keys needed: demo mode generates a deterministic factor-model market per ticker.
Install and run
git clone https://github.com/anand4286/stocklens.git cd stocklens python3 -m venv .venv && source .venv/bin/activate pip install --require-hashes -r requirements-dev.lock -r requirements-build.lock pip install --no-deps --no-build-isolation -e . uvicorn --factory stocklens.app:app_factory --port 8080
Call the API
curl -s localhost:8080/api/v1/symbols/MSFT/report \
| jq '{call: .forecast.p_up,
regime: .quant.regime.trend,
beta: .drivers.attribution.market_beta.value}'
curl -s localhost:8080/api/v1/track-record \
| jq '.simulated.scoring.verdict'Real data (optional, free tiers)
STOCKLENS_DATA_PROVIDER=alpaca STOCKLENS_ALPACA_API_KEY_ID=… STOCKLENS_ALPACA_API_SECRET_KEY=… STOCKLENS_SEC_USER_AGENT="Your Name you@example.com" STOCKLENS_ANTHROPIC_API_KEY=…
Secrets live only in your environment or a secret manager — never in the repository.
"Try it" from this page
Set Server above to your instance and press Send on any endpoint. Your instance must allow this origin: STOCKLENS_CORS_ORIGINS=["https://anand4286.github.io"]. Calls go from your browser to your server only.