# OpenVibe.Trade > Informational watchlists, sourced market context and alerts. No custody, no order execution. **Live site:** https://openvibe.trade · **API docs:** https://openvibe.services · **For AI:** https://openvibe.trade/llms.txt **Run it:** `npm ci && npm run dev` (Node 22 or newer) · **Tests:** `npm test` **Status:** alpha (roadmap Wave 19). The service runs, its tests pass, and it is **public at its domain, [openvibe.trade](https://openvibe.trade), since 2026-10-09**, after an independent pre-launch security review whose fixes shipped first. Since 2026-10-15 it carries about 8,000 US-listed companies from the SEC's own ticker list, their XBRL filings as they arrive, the key numbers in those filings, and AI briefs that cite them (see "What it shows today"). Its capabilities and service manifest are registered in openvibe-contracts. No price feed is configured. **Domain:** `openvibe.trade` · **Port:** 4860 · **Service id:** `trade` **Plan:** OpenVibe End-to-End Realignment & Implementation Plan, revision 3 (20 Sep 2026), §12.11; roadmap Wave 19, §15.13, §29, §32. **Binding decision:** ADR-025 (marketplace and commerce scope). **License:** AGPL-3.0 (same as every OpenVibe service). > **Information only — not investment advice; no trading here.** This sentence is on every page. ## Purpose An informational product: instruments and their aliases with deterministic resolution, market observations that always show when they were observed, when they were retrieved and which source stated them, filings and other source documents from OpenVibe.Sources, private watchlists, alert rules, short AI briefs written from SEC's filed numbers and filings (labelled, not reviewed by a person), and context written by editors (or drafted by OpenVibe.AI and reviewed by a person). Per ADR-025 Trade is informational **only**. There is no custody, no order execution, no escrow, no listing between users and no personalised financial advice — not as a feature, not as an endpoint, not as a table. The historical marketplace branch is recorded as an open question in [docs/marketplace-open-question.md](docs/marketplace-open-question.md), not implemented. ## Owns The nine charter tables (roadmap §15.13) live in Trade's own PostgreSQL database (`ov_trade` on the host's data role, ADR-035; schema in [migrations/](migrations/)): | Charter table | What it is | |---|---| | `trade_instruments` | Symbol (canonical, upper case), name, kind, exchange, SEC CIK, trading currency, status, and which context revision is published. Companies come from SEC's own ticker list (Sources `sec-company-tickers`, created by `svc:trade`: one per CIK, other share classes as ticker aliases); currencies from the rates; anything else from an editor. | | `trade_instrument_aliases` | Tickers, CIKs and names with their normalised resolution key. A ticker or CIK names exactly one instrument (unique index); a name may be shared (resolution is then ambiguous). | | `trade_watchlists` | Private, one owner (`usr_…`). | | `trade_watchlist_items` | Instruments on a watchlist, with an optional note. | | `trade_market_observations` | Value (the decimal exactly as stated), unit, currency, period, `observed_at`, source key, Sources item, source URL, the source's own reference, `retrieved_at`, optional `max_age_sec`, who recorded it. **Immutable** (triggers abort UPDATE and DELETE); unique per `(source_key, source_ref)`. | | `trade_source_documents` | Filings and other documents from Sources items: form type, filer, CIK, accession, URL, the source's own dates, `retrieved_at`, licence/terms notes, removal state. | | `trade_alert_rules` | `threshold` (metric, above/below, threshold, unit, currency), `filing_type` (form types) or `new_document`, one owner. | | `trade_alert_deliveries` | One row per `(rule, trigger kind, trigger id)` under a UNIQUE key — the idempotency of alerts. | | `trade_context_revisions` | `openvibe-publishing/revisions` (prefix `trade_context`): immutable revisions of an instrument's context with authorship, `as_of` and citations of Trade's documents and observations. | Other tables in the same database: - Package companions: `trade_context_drafts`, `trade_context_revision_purges`, `trade_context_reviews` (a person's review of an AI draft) and `trade_index_revisions` (the Search document sequencer). - `trade_source_status`: freshness of each source (Sources' health plus Trade's own clock). - `trade_ingest_cursor`: the change cursor of the Sources feed (`openvibe-publishing/ingest`). - `trade_sync_state`: the last sync error and counters of what was skipped and why. - `event_outbox` (SDK outbox) and `idempotency_receipts` (SDK inbox for signed webhook deliveries). - `telemetry_samples` (migration `0005_telemetry.sql`): request telemetry, openvibe-sdk 0.46 `platform.telemetry-sample@1` shape. Each request is aggregated by route template, method and status class, never by raw URL; `/shared`, static assets, health, readiness and `/metrics` are not counted. `server/app.js` builds the collector (`createHttpTelemetry`) and mounts its middleware; every minute and on stop `server/index.js` writes one `http.request` sample per key plus the active-requests, p95 latency and event-loop-lag gauges, and deletes rows older than 14 days daily. ## Does not own - **Money, custody, orders, escrow, listings, advice.** None exist here (ADR-025). Money belongs to OpenVibe.Billing (ADR-012). - **Source items.** OpenVibe.Sources owns ingestion, robots, terms and the items; Trade keeps the metadata it shows, keyed by the item id, and follows revisions and removals. - **Identity.** OpenVibe.Network: SSO, subjects, service principals. - **Notifications.** Network renders and delivers them from `trade.alert.triggered` (ADR-020). Trade sends no email. - **Search.** OpenVibe.Search indexes what Trade sends through Events. - **AI generation.** OpenVibe.AI runs `trade.summarize_market_context`; Trade makes no provider calls. - **Discussion.** Community (not wired yet; no comments here). ## What works - **Instruments and resolution.** Editors add instruments (form or API). Resolution is exact and deterministic, in a fixed order: CIK (all digits, optionally `CIK…`) → ticker (symbol, then ticker aliases) → exact normalised name (diacritics, case, punctuation, `&`, `/DE/` and trailing corporate words normalised). Several instruments with the same name → `ambiguous`, candidates listed, none chosen. No fuzzy or prefix matching. `/i/aapl` and a ticker alias answer 301 to `/i/AAPL`. - **Observations.** Recorded by a first-party feed (`POST /api/v1/observations`, `trade.observation.write`) or from Sources items that state a value: the explicit `fields.metric`, `value`, `unit`, `observed_at` (a symbol or CIK), or a rate the real trade sources state — the api adapter's `fields.rate` with `base`/`quote` (`frankfurter-eur-rates`), or a ` = 1 ` reference-rate title (`ecb-euro-reference-rates`, the value and currencies read as stated). A bare date is that day at 00:00 UTC. `observed_at` and `retrieved_at` are required and never defaulted; a replay is `200 created:false`; the same reference with a different value is `409`. A rate's quote currency with no instrument yet registers one (kind `currency`, symbol/name the stated ISO code); every other item must match an editor-created instrument or it is skipped and counted. **No observation → no number:** the page says "No observations have been recorded for X, so no number is shown." - **Freshness.** Per source: fresh only while the last successful fetch is younger than the source's window (Sources' `stale_after_sec`, else `TRADE_DEFAULT_STALE_AFTER_SEC`), computed with Trade's clock. A stale value stays visible with its timestamps and a **"stale since