Real-time detection of material events at publicly traded pharma/biotech companies from SEC 8-K filings, with a grounded briefing that explains each event through the risks the company itself already disclosed in its prior filings. Briefings are generated in English and served in Russian.
Not investment advice. Not price prediction. The system detects an event and produces a summary backed by citations from the company's own public filings. Nothing here recommends a trade or forecasts a price.
When a biotech files an 8-K ("something material happened"), the filing tells you what happened but not why it matters for that specific company. The "why" lives in the company's prior 10-K/10-Q risk disclosures, hundreds of pages nobody re-reads on the day of the event.
This platform closes that gap automatically: it watches the SEC 8-K stream, pulls the triggering company's own prior filings into a vector store on first sight, and has a local LLM write a short briefing that connects the new event to the exact disclosed risk it bears on, citing the source passage by number. The grounding is the point: the model is only allowed to cite the company's own filings, never outside knowledge, so it cannot invent a risk that was never disclosed.
- Listen. Poll the SEC EDGAR 8-K Atom feed, dedup, and keep only pharma/biotech issuers (SIC-code filter against the submissions API).
- Read the filing, not its table of contents. The feed link is an index page; the pipeline parses it, follows the primary 8-K document (stripping the iXBRL-viewer wrapper), and pulls the Exhibit 99.1 press release, where biotech substance actually lives.
- Auto-load on first material event. If the company has no chunks in the vector store yet, fetch its latest 10-K + 10-Q, extract Risk Factors, chunk, embed, and store, once per company.
- Ground. Retrieve that company's risk factors (CIK-locked, Risk-Factors section first) and have the LLM compose a 3-5 sentence briefing with numbered citations, linking the event to disclosed risk by theme, not keyword.
- Translate. A separate, larger model renders the English briefing into Russian; the English stays the source of truth.
- Serve. A read-only web feed shows the newest events as cards with highlighted citations, updating live without a full page reload.
Three decoupled processes that talk only through Postgres, so one failing never takes down the others:
- Listener (no GPU): EDGAR polling, SIC filter, writes events.
- Briefing worker (dual-GPU): event extraction, auto-load, grounded briefing, translation.
- Web feed (no GPU): read-only Flask/gunicorn feed.
Dual-GPU layout, one model per card. The EN briefing model (7B) sits on one GPU, the RU translation model (14B) on the other, so briefing and translation never evict each other. The sentence-embedding model shares a card with the 14B; its context is capped so the KV cache cannot starve the embedder, and the embedder falls back to CPU on a CUDA OOM and returns to GPU on the next call. Degrade, don't die.
- Grounded, citation-only prompting as a hallucination guard. The LLM may cite only the numbered source passages. A category gate keeps routine/administrative filings away from the LLM entirely, so it never fabricates a risk linkage where none exists; those get an honest fixed note instead.
- Event is description, source is citation. The Exhibit 99.1 press release tells the model what happened; the numbered sources remain the company's prior risk disclosures. Keeping the two roles separate is what keeps citations honest.
- The
/ix?doc=trap. EDGAR links the primary document through an iXBRL JavaScript viewer; downloading it raw returns the viewer shell, not the document. The index parser strips the wrapper and takes the real path, a real-world quirk that silently breaks naive scrapers. - Translation as a separate layer, not generation in Russian. Translating a finished, grounded English summary is more reliable than asking a model to produce grounded Russian from scratch; facts and citations stay fixed.
- GPU memory contention, handled at two layers. Capped translator context + embedder CPU fallback, after diagnosing "empty cards" to KV cache ballooning rather than to EDGAR or foreign filers.
Python · PostgreSQL + pgvector · sentence-transformers (MiniLM, 384-dim) · Ollama (two instances, qwen2.5-7B + qwen3-14B) · dual NVIDIA GPUs · Flask + gunicorn · systemd (services + timer) · Graphviz.
ingestion/ EDGAR listener, SIC filter, CIK->ticker, DB access
rag/ fetch, clean, chunk, embed, vector store, event extraction,
index/exhibit parsing, grounded briefing, translation, worker
web/ read-only feed (server-rendered cards + JSON endpoint for
incremental refresh)
db/ schema + migrations
deploy/ systemd unit files
tests/ offline tests (no network / GPU / DB)
docs/ architecture diagram + full engineering wiki
| Date | Milestone |
|---|---|
| 2026-09-19 | v1. Listener + SIC filter, RAG loader with Risk Factors extraction, grounded briefing with category gate and risk-term query enrichment, web feed, systemd units, reboot-tested. |
| 2026-09-28 | v2. Auto-load a company's filings on its first material event; separate Russian translation layer; live listener and worker fully autonomous. |
| 2026-09-29 | v2.1. Exhibit-99 aware extraction (index -> primary doc -> press release, /ix?doc= strip, Reg FD promotion); GPU-contention fixes (capped translator context, embedder CPU fallback); periodic translation-sweep timer. |
| 2026-09-29 | v2.2. Git-based deployment across hosts; live web feed (incremental JS refresh, no full reload). |
Fully autonomous: live listener, auto-loading, grounded EN briefing, RU translation, live feed, all under systemd.
- Pharma is a thin stream; an empty feed with a live listener is normal (EDGAR is near-silent on weekends).
- Briefing quality depends on a matching risk factor existing in the company's filings. Small biotechs with no 10-K get an honest "no prior filings" note rather than an invented link.
- "Real-time" is polling; the SEC has no push feed. Named honestly.
- Russian is a translation of the English briefing; citation numbers refer to the English source passages.
Portfolio project. Built on a personal RHEL/GPU homelab as part of a pivot toward LLM/GPU infrastructure and MLOps engineering.
