Skip to main content
Glama
QuotaFuse-ai

TickHub-US

by QuotaFuse-ai

TickHub-US does one thing: it turns US / HK market data scattered across 20 sources into structured tools a model can call directly.

Every number must come from a tool call, and must carry its source and compliance tier. Quotes, K-lines, financial statements, options chains and unusual flow, short data, SEC filings and 13F, policy rates, energy — the service fetches, normalizes and caches them, then returns a single DataEnvelope instead of asking the model to remember numbers or stitch URLs itself.

It is a deployable standalone service, not a prompt. Three things come with that: process isolation (a real process exposing MCP stdio / Streamable HTTP plus a th-us CLI), compliance interception (a commercial call against a disallowed tier raises ComplianceError and does not walk the fallback chain) and cache degradation (Redis when available, in-process LRU when not, with an explicit warning).

  • 41 MCP tools + ten th-us CLI groups, same response shape at every entry point.

  • 20 sources graded S / B / C / D (plus tier X, never integrated); the grade is enforced at the call site, not in documentation.

  • Fallback order and compliance grades live in YAML, so changing a source is a config change, not a release.

  • Optional Redis, automatic LRU fallback, and cache keys that separate commercial from non-commercial calls.

  • The wheel ships its own config, so pip install works from any directory.

This project distributes code, not market data. Data is fetched by the user under each source's own terms. For commercial use, rely only on tier-S sources.


Why TickHub-US

One sentence: direct API calls give you freedom, aggregation libraries give you breadth, and TickHub-US gives you "a model can retrieve sourced, compliance-tagged data without writing code".

Dimension

TickHub-US

Calling Yahoo / Eastmoney directly

Aggregator libraries (mostly A-shares)

Paid market-data APIs

How you call it

MCP tools, CLI and Python share one response

Build URLs, supply UA / crumb, parse fields

Python functions, one DataFrame per function

SDK + subscription

Auth

Zero-key quotes; SEC needs only a contact email

Maintain cookies, crumbs, throttling yourself

Zero-key

Signup, payment, quota

Compliance

Every source graded S / B / C / D; commercial calls blocked and logged

Read the terms and judge yourself

Not distinguished

Covered by contract

Multi-source fallback

Chains declared in YAML, every attempt recorded

Write your own retries and fallbacks

Partial

Usually single-source

US / HK

US + HK quotes and K-lines; Taiwan via official open data

Inconsistent endpoints per site

Mostly A-shares

Bought per plan

SEC depth

Filings, full-text search, XBRL, 13F, Form 4 — all free, tier S

Implement CIK mapping and paging yourself

Partial

Usually bought separately

Response shape

One envelope with source / freshness / trace_id

Raw JSON that changes with the site

DataFrame

Varies

License / cost

Apache-2.0; data under each source's terms

—

MIT / Apache

Commercial subscription

Best for

AI agents and automation that needs a compliance stance

Deep customization of one endpoint

Data exploration and research

Institutions with SLAs


Related MCP server: Stock MCP

Architecture

TickHub-US · MCP Server + CLI · v1.0.0
│
├── Access       MCP stdio / Streamable HTTP (41 tools) + th-us CLI (10 command groups)
│                ↳ commercial_use is mandatory at the entry point; missing → ComplianceError
│
├── Orchestration
│                Fallback chain (config/sources.yaml) → try each source → record all attempts
│                Compliance gate (config/compliance.yaml) → tier decision → denial is final
│                Cache (Redis, auto-degrades to in-process LRU) → per-domain TTL
│
├── Domains      quotes / K-lines / indicators / fund flow / short / volatility / Taiwan
│                fundamentals / statements / key metrics / analysts / institutional holders
│                options chain / unusual flow / CBOE quotes
│                SEC filings / daily feed / full-text / XBRL / insiders / 13F
│                macro / rates / FX / energy
│
└── Adapters     20 providers, each registering a compliance_source
                 SEC EDGAR · Treasury · CFTC · Fed Board · NY Fed · BIS · ECB · EIA · EIA spot
                 TWSE · TPEx · FINRA · CBOE · Eastmoney · Sina · Tencent · Polygon · Yahoo · Nasdaq · local

Design trade-off: source priority is written in YAML, not code — one line changes the fallback order. Compliance works the same way: the code only knows compliance_source. When a source changes its terms, that is a config change, not a release.


Compliance tiers

Source terms differ a lot, and "official" does not mean "free to use". These grades come from reading each source's actual terms; the full text is in config/compliance.yaml.

A working HKEX shareholding layer was removed. Shipping scraping code that violates a source's terms would defeat the point of grading sources in the first place.

Why keep tier-D Yahoo and Nasdaq? The difference is whether a substitute exists: Yahoo is the only source for HK K-lines and for markets beyond the US and HK, and Nasdaq is the only key-free earnings calendar. So the code stays and the terms are quoted in full; whether to use them is the user's call under those terms.

The gate really fires, and it is not a documentation convention:

  • commercial_use=false: S / B / C / D are all callable; C / D carry warnings.

  • commercial_use=true: S passes; tier B is denied by default and can be whitelisted per source; C / D raise ComplianceError and never walk the fallback chain to get around it.

  • If every source on the chain is denied by compliance, the call raises ComplianceError instead of silently degrading.


Quick start

Distribution name tickhub-us · Python package tickhub_us · CLI th-us. Requires Python ≥ 3.11.

3 steps, 2 minutes.

# 1. Install (PyPI 1.0.0, published 2026-10-26)
pip install tickhub-us
# or from a checkout
git clone https://github.com/QuotaFuse-ai/TickHub-US.git
pip install -e TickHub-US
# development
pip install -e "TickHub-US[dev]"

# 2. Declare your SEC contact (EDGAR requires a real name + email; missing → E_CONFIG)
export SEC_CONTACT="Zhang San zhangsan@example.com"

# 3. Try one call
th-us quote get AAPL
th-us quote get AAPL --output json      # stdout is JSON only, logs go to stderr

A real response, captured 2026-10-26 (fields elided):

{
  "schema_version": "1.0",
  "domain": "quote_us",
  "symbol": "AAPL",
  "payload": {
    "symbol": "AAPL",
    "price": 347.725,
    "prev_close": 348.22,
    "change_pct": -0.14,
    "high_52w": 348.36,
    "low_52w": 242.89,
    "pe": 41.89,
    "eps": 8.3,
    "currency": "USD"
  },
  "source": "sina",
  "compliance_tier": "C",
  "freshness": "realtime",
  "fetched_at": "2026-10-26T08:35:47Z",
  "cache_hit": false,
  "trace_id": "54dc2aebd9904304",
  "warnings": ["新浪财经 属 Tier C:商用需事先书面许可,当前为非商用调用。"],
  "attempts": [
    { "provider": "polygon", "status": "disabled" },
    { "provider": "sina", "status": "ok", "tier": "C" }
  ]
}

Look at compliance_tier and warnings: this row came from Sina, a tier-C source, so the same call with commercial_use=true is rejected outright. attempts shows Polygon skipped for lack of a key and Sina answering.

One-click install

Four distribution channels, one code base — PyPI wheel / sdist, GitHub Release assets, GHCR container image, and source install. All three published channels are live as of v1.0.0. See Publishing.

# PyPI
pip install tickhub-us
th-us quote get AAPL

# Container (stdio, launched by the MCP client)
docker run --rm -i -e SEC_CONTACT="Zhang San zhangsan@example.com" \
  ghcr.io/quotafuse-ai/tickhub-us

# Container (HTTP, published to loopback only)
# Binding a non-loopback address inside the container requires a bearer token
# and a Host allowlist, so the two env vars below are not optional.
docker run --rm -p 127.0.0.1:8001:8001 \
  -e MCP_HTTP_TOKEN=change-me \
  -e MCP_HTTP_ALLOWED_HOSTS=127.0.0.1:8001 \
  ghcr.io/quotafuse-ai/tickhub-us \
  mcp http --host 0.0.0.0 --port 8001

pip install places config/sources.yaml and config/compliance.yaml under <prefix>/share/tickhub-us/config, so the CLI works from any directory. Source installs find the repo's config/ automatically; TICKHUB_US_CONFIG_DIR overrides both.

Connect to an MCP client

# stdio (preferred for local agents)
th-us mcp stdio

# Streamable HTTP
th-us mcp http --host 127.0.0.1 --port 8001

# Both at once
th-us start-all

MCP client configuration (Claude Desktop style):

{
  "mcpServers": {
    "tickhub-us": {
      "command": "th-us",
      "args": ["mcp", "stdio"],
      "env": { "SEC_CONTACT": "Zhang San zhangsan@example.com" }
    }
  }
}

Commercial calls

Every data call requires an explicit commercial_use (an MCP tool argument, or --commercial-use on the CLI). That is the only mechanism that puts compliance at the call site — an agent cannot violate a source's terms without saying so.

# Whitelist specific tier-B sources (a non-empty whitelist is authoritative)
export TICKHUB_US_ALLOW_TIER_B_SOURCES=finra,eia_spot

# Or allow all tier-B sources (coarse switch)
export TICKHUB_US_ALLOW_TIER_B_COMMERCIAL=true

# Polygon commercial use: the key alone is not enough, confirm the subscription
export POLYGON_API_KEY=...
export TICKHUB_US_POLYGON_COMMERCIAL_BASIS=true

Endpoints

Price — Sina / Tencent / Eastmoney real-time quotes (US + HK) · Sina K-lines (US back to 1984) · Yahoo K-lines (HK and markets beyond US/HK) · MA / EMA / MACD / RSI / KDJ / BOLL computed locally.

Value — Eastmoney three statements + key indicators (including HK) · Yahoo quoteSummary structured statements / analyst estimates / institutional holders · SEC XBRL companyfacts.

Flow & positioning ⭐ — FINRA market-wide daily short volume and short interest (with days to cover and rankings) · CBOE options chains (IV + full Greeks) and unusual-flow detection · CBOE volatility indices (VIX since 1990) and the VIX term structure · Eastmoney daily fund flow.

Filings & events ⭐ — EDGAR submissions · daily index event stream (same-day Form 4 / 8-K / 13F) · full-text search back to 2001 · Form 4 insider trades line by line · 13F institutional holdings · XBRL frames market-wide cross-section (a free screener).

Macro / rates ⭐ — Treasury yield curve · CFTC COT · earnings calendar · Treasury auctions and federal debt · BIS central-bank policy rates · ECB FX / rates / yield curve · NY Fed SOFR / EFFR · Fed Board H.10 / H.6.

Taiwan / energy ⭐ — TWSE + TPEx official open APIs (quotes / P/E / monthly revenue / margin) · EIA weekly crude and natural gas inventories plus spot prices.

Tools — stock search · full-market list · per-symbol and keyword news · ticker ↔ CIK.

Quotes / K-lines / technical indicators

Endpoint

Sources (tier)

Data

th-us quote get / th_us_get_quote

Polygon(C) → Sina(C) → Tencent(C) → Eastmoney(C)

US / HK real-time snapshot: last, change, volume, 52-week high/low

th-us quote kline / th_us_get_market_data

Polygon(C) → Sina(C) → Yahoo(D)

Daily / weekly / monthly / minute OHLCV, US back to 1984

th-us quote indicators / th_us_technical_indicators

local(S)

MA / EMA / MACD / RSI / KDJ / BOLL; the underlying K-line's tier is recorded in underlying

th-us quote flow

Eastmoney(C)

Daily main / large / medium / small order fund flow

th-us quote list / th_us_get_market_list

Eastmoney(C)

Full US / HK market list with paging

th-us quote taiwan / tw-market

TWSE(S) → TPEx(S) → Yahoo(D)

Taiwan quotes, P/E, monthly revenue, margin trading

th-us quote search / th_us_search_stocks

Yahoo(D) → Eastmoney(C) → SEC(S)

Stock search in Chinese and English

th-us quote news / th_us_get_news

Yahoo(D)

News by ticker or keyword

Short data / volatility ⭐

Endpoint

Sources (tier)

Data

short-volume / short-volume-all / short-volume-rank

FINRA(B)

Daily short volume: per-symbol series, market-wide, ratio ranking

short-interest / short-interest-all / short-interest-rank

FINRA(B)

Open short positions twice a month, days to cover, change vs prior period and rankings

volatility / th_us_get_volatility

CBOE(C)

VIX (since 1990) / VIX9D / VIX3M / VVIX / SKEW / OVX / GVZ daily

vix-structure

CBOE(C)

Latest VIX at each tenor, contango vs backwardation, long-short spread

Fundamentals

Endpoint

Sources (tier)

Data

th-us finance stats / th_us_get_fundamentals

Eastmoney(C) → Yahoo(D) → SEC(S)

Valuation, earnings, growth, target price, company profile

th-us finance statements / get_financial_statements

Eastmoney(C)

Three statements (US / HK)

th-us finance yahoo-statements

Yahoo(D)

Structured three statements (annual / quarterly)

th-us finance indicators / get_key_indicators

Eastmoney(C)

Key financial indicators

th-us finance analyst / get_analyst_estimates

Yahoo(D)

Analyst estimates and rating trend

th-us finance holders / get_institutional_holders

Yahoo(D)

Institutional holdings overview and top ten

Options

Endpoint

Sources (tier)

Data

th-us options chain / get_options_chain

CBOE(C) → Yahoo(D)

Full chain + IV + delta / gamma / vega / theta / rho

th-us options flow / get_options_flow

CBOE(C) → Yahoo(D)

Unusual-flow detection (vol/OI > 1 = new positioning), with a 0DTE filter

th-us options cboe

CBOE(C)

CBOE official delayed quotes for the underlying

Filings / insiders / 13F ⭐

Endpoint

Sources (tier)

Data

th-us finance report / search_filings

SEC(S)

One company's filing list (10-K / 10-Q / 8-K …)

th-us finance feed / get_filing_feed

SEC(S)

EDGAR daily index event stream, whole market for the day

th-us finance fulltext / fulltext_search

SEC(S)

Full-text search of filing bodies back to 2001

th-us finance insider / get_insider_trades

SEC(S)

Form 4 line by line: type, shares, price, holdings after, 10b5-1 flag

th-us finance 13f / get_13f_holdings

SEC(S)

Quarterly institutional holdings, sorted by value with weights, reconcile against the cover total

th-us finance xbrl / get_xbrl_facts

SEC(S)

Raw companyfacts view

th-us finance frame / screen_market

SEC(S)

XBRL frames market-wide cross-section = a free screener

th-us finance cik / lookup_cik

SEC(S)

ticker → 10-digit CIK

Macro / rates / FX ⭐

Endpoint

Sources (tier)

Data

th-us macro curve / get_treasury_yield_curve

Treasury(S)

Yield curve 1M ~ 30Y

th-us macro cot / get_cot

CFTC(S)

COT positioning report

th-us macro earnings

Nasdaq(D)

Earnings calendar (pre/post market and EPS estimates)

th-us macro fiscal / get_treasury_fiscal

Treasury(S)

Treasury auctions, federal debt, average interest rates

th-us macro rates / get_policy_rates

BIS(S) → ECB(S) → NY Fed(S) → Fed(S) → Treasury(S)

Global central-bank policy rates (48 economies in one call)

th-us macro ecb-fx / ecb-rates / ecb-curve / ecb-series

ECB(S)

Euro reference rates, three key rates, euro-area curve, any series

th-us macro nyfed / get_nyfed_rates

NY Fed(S)

SOFR / EFFR / OBFR / TGCR / BGCR, with percentiles and volume

th-us macro fed / get_fed_releases

Fed Board(S)

H.10 FX, H.6 money stock

Energy ⭐

Endpoint

Sources (tier)

Data

th-us macro energy / get_energy_prices

EIA spot(B)

WTI (since 1986) / Brent / Henry Hub daily spot prices

th-us macro inventories / get_energy_inventories

EIA(S)

Weekly crude (commercial + SPR), gasoline, distillate and natural gas inventories

Diagnostics

Endpoint

Data

th-us compliance check / list

Look up a source's tier decision and the terms behind it

th-us source list / chain

Show sources and fallback chains

th-us cache status / clear

Cache status and clearing

th-us config show

Current runtime settings (secrets redacted)


Usage examples

Say these to your AI assistant to trigger the tools (the CLI equivalent is in parentheses):

Scenario

What to say

US / HK quote

"What's AAPL trading at, and its PE?" · "How's Tencent 00700 today?" (th-us quote get 00700)

K-line

"Pull TSLA's daily K-line for the past six months" (th-us quote kline TSLA)

Technical analysis

"Is AAPL's MACD crossing its RSI?" (th-us quote indicators AAPL)

Statements / valuation

"Apple's latest quarterly income statement" · "BABA's PE/PB/ROE and target price"

Institutional holdings

"Which institutions hold NVDA, and what percentage?"

0DTE options flow ⭐

"Show me NVDA's 0DTE unusual options activity" (th-us options flow NVDA)

Short volume ⭐

"TSLA's short-volume ratio trend this week"

Short interest ⭐

"GME's recent short interest and days to cover"

VIX term structure ⭐

"Is the VIX term structure inverted right now?" (th-us quote vix-structure)

Insider filings ⭐

"Which Form 4 insider filings came out today?" (th-us finance feed --type 4)

Insider trades ⭐

"How many shares have NVDA executives sold in the past six months?" (th-us finance insider NVDA --days 180)

13F holdings ⭐

"Berkshire's top ten 13F holdings last quarter" (th-us finance 13f 1067983)

Filing full-text ⭐

"Which companies mention HBM4 in an 8-K for the first time?" (th-us finance fulltext HBM4)

Market-wide screen ⭐

"Rank the whole market by R&D expense for CY2025Q1" (th-us finance frame ResearchAndDevelopmentExpense)

Macro

"What's the 10Y-2Y Treasury spread right now?" (th-us macro curve)

Central banks ⭐

"Current policy rates of the major central banks" (th-us macro rates)

FX / Treasuries ⭐

"EUR/JPY this month" · "Next week's Treasury auction schedule"

Taiwan ⭐

"TSMC's latest close and P/E" (th-us quote taiwan 2330)

Oil / gas ⭐

"This week's EIA crude inventories" (th-us macro inventories)

Other markets

"Toyota 7203.T daily K-line for the past year" (Yahoo, tier D)

Batch compare

"Compare valuations of AAPL MSFT GOOGL"


Data sources

Source

Tier

Auth

Coverage

SEC EDGAR

S

real UA (SEC_CONTACT)

Filing lists / daily event stream / full-text search / XBRL / frames / Form 4 / 13F / CIK

US Treasury

S

none

Yield curve / auctions / federal debt / average rates

CFTC

S

none

COT positioning reports

Federal Reserve Board

S

none

H.10 FX / H.6 money stock (attribution required)

NY Fed

S

none

SOFR / EFFR / OBFR / TGCR / BGCR (notice required when shown to others)

BIS

S

none

Central-bank policy rates (attribution required)

ECB

S

none

EUR FX / three key rates / euro-area yield curve (attribution; no modification)

US EIA (inventories)

S

none

Weekly crude / natural gas inventories (attribution recommended)

US EIA (spot prices)

B

none

WTI / Brent / Henry Hub spot (Refinitiv data republished by EIA; verify before commercial use)

Taiwan Stock Exchange (TWSE)

S

none

Listed stocks' quotes / P/E / monthly revenue / margin trading (attribution)

TPEx

S

none

OTC stocks' quotes / P/E / monthly revenue / margin trading (attribution; tier S is this project's judgment)

FINRA

B

none

Market-wide daily short volume / short interest (verify before commercial use)

CBOE

C

none

Options chains + Greeks + IV / VIX and other volatility indices (needs Cboe's prior approval)

Eastmoney (push2 / push2his / datacenter / search)

C

none

US + HK quotes / fund flow / statements / key indicators / market list

Sina

C

none

US + HK quotes, US K-lines

Tencent

C

none

US + HK quotes

Polygon

C

API key (optional)

US quotes and K-lines (commercial use needs the subscription terms confirmed)

Yahoo Finance

D

cookie + crumb (auto)

HK / other-market K-lines, statements, analysts, holders, options fallback, search, news

Nasdaq

D

none

Earnings calendar

Local indicator computation

S

none

MA / EMA / MACD / RSI / KDJ / BOLL computed from fetched K-lines

Tiers: S = government and central-bank data, commercial + redistribution OK (some require attribution) · B = published but terms-restricted, verify before commercial use and do not redistribute · C = needs prior approval or personal research only · D = terms prohibit automated access without permission; personal study and research only, at your own risk. Quoted basis: Compliance tiers.

All requests go through core/http.py: per-host rate limiting (SEC 8 req/s, CFTC / FINRA / CBOE 4 req/s, Nasdaq 2 req/s, default 5 req/s), exponential-backoff retries, an 8 MB response cap, and cross-host redirects allowed only to hosts registered in config/sources.yaml.


Configuration

Everything is environment variables. A .env file in the current directory (or its parent) is loaded automatically on first use. th-us config show prints the effective settings with secrets redacted.

Data-source access

Variable

Default

What it does

SEC_CONTACT

—

Real name + email placed in the EDGAR User-Agent. Required for every SEC tool; missing raises E_CONFIG

POLYGON_API_KEY

—

Optional Polygon key. Without it the polygon provider is skipped and the chain moves on

TICKHUB_US_ALLOW_TIER_B_SOURCES

—

Comma-separated tier-B whitelist (finra,eia_spot). A non-empty list is authoritative: unlisted sources stay denied even if the global switch is on

TICKHUB_US_ALLOW_TIER_B_COMMERCIAL

false

Coarse switch: allow all tier-B sources for commercial calls

TICKHUB_US_POLYGON_COMMERCIAL_BASIS

false

Explicit acknowledgement that your Polygon subscription permits commercial use; the key alone is not enough

YAHOO_ENABLE

true

Set to false to disable the tier-D Yahoo provider entirely

Runtime and cache

Variable

Default

What it does

TICKHUB_US_CONFIG_DIR

auto

Config directory override. Resolution order: this variable → ./config → repo layout → <prefix>/share/tickhub-us/config

TICKHUB_US_TTL_SECONDS

—

Global TTL override in seconds. Without it each domain uses the ttl from sources.yaml

CACHE_ENV

prod

prod / dev (caps TTL at 60 s) / off (disable caching). Also namespaces Redis keys

REDIS_URL

redis://127.0.0.1:6379/0

Redis connection. Unreachable Redis degrades to the in-process LRU with a warning

LOG_LEVEL

info

Log level

HTTP_TIMEOUT

20.0

Per-request timeout in seconds

HTTP_RETRIES

2

Retry count per request

HTTPS_PROXY / HTTP_PROXY

—

Standard proxy variables; requests reads them automatically

MCP HTTP server

Variable

Default

What it does

MCP_HTTP_HOST

127.0.0.1

Bind address. Non-loopback requires MCP_HTTP_TOKEN; 0.0.0.0 / :: also requires MCP_HTTP_ALLOWED_HOSTS

MCP_HTTP_PORT

8001

Listen port

MCP_HTTP_PATH

/mcp

Streamable HTTP path

MCP_HTTP_TOKEN

—

Bearer token. When set, every request except GET /healthz must send Authorization: Bearer <token>

MCP_HTTP_ALLOWED_HOSTS

—

Extra Host allowlist entries (comma-separated), e.g. tickhub.internal:8001

MCP_HTTP_ALLOWED_ORIGINS

—

Extra Origin allowlist entries (comma-separated)

commercial_use is not an environment variable — it is a per-call parameter, deliberately, so that no deployment-wide setting can flip a whole process into commercial mode by accident.


Fallback chains and cache

config/sources.yaml defines one chain per domain. A failure (throttle / no data / compliance denial / upstream 5xx) is recorded in DataEnvelope.attempts and the next source is tried:

quote_us:  polygon → sina → tencent → eastmoney    # TTL 30s,  realtime
fundamental: eastmoney → yahoo → sec_edgar         # TTL 12h,  eod
rates: bis → ecb → ny_fed → federal_reserve → treasury
options_flow: cboe → yahoo                          # TTL 60s, realtime

Cache TTLs are per domain: quotes 30 s, options 60 s, news 5 min, statements and filings 12 h, CIK mapping 24 h. When Redis is unavailable the cache degrades to an in-process LRU and says so in the log — cache degradation never changes which data source is used. Cache keys include the commercial_use flag, so a commercial result is never served to a non-commercial call.

DataEnvelope

Every response uses the same envelope, so an agent can consume source / freshness / compliance_tier / attempts directly:

{
  "schema_version": "1.0",
  "domain": "quote_us",
  "symbol": "AAPL",
  "payload": { "...": "..." },
  "source": "sina",
  "compliance_tier": "C",
  "freshness": "realtime",
  "fetched_at": "2026-10-26T01:30:00Z",
  "cache_hit": false,
  "trace_id": "9f2c1e7a4b6d0c33",
  "warnings": ["新浪财经 属 Tier C:商用需事先书面许可,当前为非商用调用。"],
  "attempts": [{ "provider": "polygon", "status": "disabled" }]
}

(The warnings string is read from config/compliance.yaml and is currently Chinese-only; callers should treat it as opaque text, not parse it.)

Technical indicators additionally carry underlying, which records the source and tier of the K-lines they were computed from: the indicator itself is tier-S local computation, but its trustworthiness depends on its input, and that tier stays visible to the caller.

MCP tools

41 tools in total, grouped below. The three signatures fixed by the product spec:

Tool

Purpose

th_us_get_market_data(symbol, interval, commercial_use)

Quotes / K-lines / indicators

th_us_search_filings(symbol, form_type, commercial_use)

SEC filing search

th_us_get_options_flow(symbol, commercial_use)

Options chain and unusual flow

Category

Tools

Quotes / technicals

get_quote, get_market_data, technical_indicators, get_fund_flow, get_volatility (term_structure switches to the VIX term structure), get_short_volume, get_short_interest (both accept scope=symbol/all/rank), get_taiwan_stock, get_taiwan_market, get_market_list

Fundamentals

get_fundamentals, get_key_indicators, get_financial_statements, get_analyst_estimates, get_institutional_holders

Options

get_options_chain, get_options_flow

Filings / insiders

search_filings, get_filing_feed, fulltext_search, get_insider_trades, get_13f_holdings, get_xbrl_facts, screen_market, lookup_cik

Macro / rates / energy

get_treasury_yield_curve, get_policy_rates, get_cot, get_earnings_calendar, get_ecb (kind=fx/key_rates/curve/series), get_nyfed_rates, get_fed_releases, get_treasury_fiscal, get_energy_prices, get_energy_inventories

Tools / diagnostics

search_stocks, get_news, check_compliance, list_compliance_policies, list_providers, cache_status

(The th_us_ prefix is omitted above.)

MCP HTTP security

By default the server listens on loopback only (127.0.0.1 / localhost / [::1]) with DNS-rebinding protection always on. The Host / Origin allowlists are passed explicitly by create_app(); in the loopback case only loopback hosts are allowed.

Listening externally is an explicit action — missing one requirement fails startup with E_CONFIG:

Scenario

Requirement

MCP_HTTP_HOST=127.0.0.1

none

Bind a specific interface (e.g. 10.0.0.5)

MCP_HTTP_TOKEN is required

Bind 0.0.0.0 / ::

MCP_HTTP_TOKEN and MCP_HTTP_ALLOWED_HOSTS are required

With MCP_HTTP_TOKEN set, every request except GET /healthz (kept anonymous for container probes) must carry Authorization: Bearer <token>. The check uses a constant-time comparison; failures return 401 with WWW-Authenticate: Bearer realm="tickhub-us". /healthz returns only {"status": "ok"} — no version, no tool count (SEC-12).

MCP_HTTP_HOST=0.0.0.0 \
MCP_HTTP_TOKEN="$(openssl rand -hex 32)" \
MCP_HTTP_ALLOWED_HOSTS=tickhub.internal:8001 \
th-us mcp http

FinanceCoffer event stream

On top of the MCP / CLI surface, TickHub-US can publish what it already collects as standard events for the downstream warehouse FinanceCoffer. The event contract (Event Contract v1) lives in the FinanceCoffer repository and is shared by both ends.

The publisher is a sidecar (us_collector), not part of the MCP server process — if you never start it, nothing is published.

# Dry run first: assemble events, print a summary, write nothing
python -m us_collector.scheduler --config us_collector/config.yaml --once --dry-run

# One real round
python -m us_collector.scheduler --config us_collector/config.yaml --once

# Scheduled sidecar: 17:30 America/New_York, weekdays
python -m us_collector.scheduler --config us_collector/config.yaml

Item

Value

Target stream

fc:stockdata:events

Consumer group (downstream)

fc-etl

Dead-letter stream

fc:stockdata:dlq

schema_version

"1.0"

Retention

XADD MAXLEN ~ 100000 (Redis must have AOF enabled)

Event types

quote, kline, financial, announcement, risk, heartbeat

Provider

tickhub-us

Compliance

compliance_tier per source; commercial_use=false, enforced at startup

Design notes:

  • Sidecar, never fatal: Publisher.publish does not raise into the collector. When Redis is unavailable the event goes to a SQLite outbox (var/us_collector/outbox.sqlite3) and is flushed later with bounded retries; a run that cannot publish still completes.

  • Deterministic event_id: an evt_ prefix plus a hash of the business key, so retries and duplicates collapse into one row downstream.

  • Exactly one instance: a PID lock (var/us_collector/scheduler.lock) makes a second scheduler exit with code 2 instead of double-publishing.

  • Heartbeat on non-trading days: US market holidays publish data_type=heartbeat only — no tool is called and no data event is emitted.

  • Amounts stay strings: decimal amounts are validated as strings and never round-tripped through a float.

Field definitions, failure handling and versioning: docs/specs/event-contract.md.

Amount units and valuation fields (QUOT-249)

The contract requires amounts in the basic currency unit of that market — USD for US listings, HKD for HK. quote_us resolves through polygon → sina → tencent → eastmoney (config/sources.yaml), and the vendors do not publish market cap at the same scale, so the value the warehouse saw depended on which vendor answered first:

Provider

Vendor market-cap scale (recorded 2026-10-30, AAPL)

Event value

sina

absolute USD — 5093610331345.0

passed through unchanged

tencent

亿美元 / 亿港元 — 50920.55344

× 1e8

eastmoney

none in the requested field list

absent + total_market_cap in missing_fields

polygon

not mapped out of the snapshot

absent + total_market_cap in missing_fields

any other

not probed

absent + total_market_cap_unit_unknown:provider=<name>

A provider that is not in the table is treated as unknown, not as scale 1 — the collector would rather publish no amount than a guessed order of magnitude. Scales are pinned by magnitude evidence (market cap ÷ price = shares outstanding) and per-provider fixtures, one file entry per vendor; see UNIT-AUDIT.md.

quote events also carry pb_mrq — the vendor's most-recent-quarter price-to-book, the same number as pb, published under that name because it is the ratio the downstream reference basis reads. It is emitted only when strictly greater than zero; otherwise the field stays absent and pb_mrq appears in quality_metrics.missing_fields. US/HK reference values are expected to stay null downstream this phase (no currency column in dwd.stock_quote_snapshot) — that is a recorded limitation, not a defect.

US biz_key values for quote end in a field-generation tag |g2 (the unit normalisation above). event_id hashes only provider|data_type|symbol|biz_key, and the downstream DWD layer is append-only and dedupes by that id, so a corrected amount re-published under the old key would be dropped as a replay. Cutover and existing data: UNIT-AUDIT.md §5.

Testing and CI

Suite

Cases

Covers

Offline

238

Contracts, compliance interception, fallback-chain matrix, secret redaction, input and network hardening, MCP HTTP security, indicator tier inheritance, regression tests for live defects

Live smoke

13

US / HK quotes · SEC filings and 13F · options flow · VIX history and term structure · EIA spot and inventories · BIS policy rates · Yahoo fundamentals; skipped by default

# Full offline run (no network, no Redis needed)
pytest -m "not live"

# Live smoke (needs SEC_CONTACT; Eastmoney endpoints can be skipped outside mainland China)
SEC_CONTACT="you@example.com" TICKHUB_US_LIVE=1 pytest tests/contract/test_live_smoke.py -m live
TICKHUB_US_LIVE_SKIP_REGIONAL=1 ...   # skip the two cases that depend on Eastmoney push2

CI (.github/workflows/ci.yml):

  • push / pull_request: Python 3.11 + 3.12 matrix, ruff → compileall → offline tests, as the merge gate;

  • workflow_dispatch with live checked: an extra networked job that reads the repository variable SEC_CONTACT (cases skip themselves when it is unset, so the job never goes red) and the optional POLYGON_API_KEY secret, and skips the Eastmoney cases that are unreachable from overseas. Writing code needs no keys; running against live sources does.

Exact check names, copy-paste equivalents for Windows and Linux, and the current required-check status (main is unprotected and there are no rulesets, so CI is advisory only): docs/CI.md.

Two manual release workflows, neither triggered by a push:

Workflow

What it does

publish.yml

python -m build → twine check --strict → install and run the wheel in a clean venv (proving it does not need the source tree) → publish to TestPyPI or PyPI (OIDC trusted publishing, no token) → when publishing to PyPI, also create a GitHub Release with the sdist / wheel attached

docker.yml

Build and push ghcr.io/quotafuse-ai/tickhub-us (version tag + latest) → pull it back and run a real smoke: anonymous /healthz works, MCP initialize with a Bearer token works, an unauthenticated POST returns 401

Operating steps and the one-time PyPI setup are in Publishing. If egress needs a proxy, set HTTPS_PROXY / HTTP_PROXY (the standard variables requests reads); keep proxy credentials in the environment only — never in config/ and never committed.

Publishing

Both channels are manual dispatch only — pushing a commit or a tag uploads nothing.

PyPI / TestPyPI (publish.yml, already live at 1.0.0):

  • Run Actions → Publish to PyPI → Run workflow, pick pypi or testpypi. Auth is GitHub OIDC (Trusted Publishing); no token is stored in the repository.

  • One-time setup, needed only for a new project or environment: on the index, Publishing → Add a new pending publisher with project tickhub-us, owner QuotaFuse-ai, repository TickHub-US, workflow publish.yml, environment pypi (or testpypi, a separate account).

  • A version, once uploaded, cannot be replaced — bump version in pyproject.toml before re-running. Upload the exact artefacts that passed twine check --strict; do not rebuild between check and upload.

Container (docker.yml): builds and pushes ghcr.io/quotafuse-ai/tickhub-us with the version tag plus latest, then pulls it back and smokes it (anonymous /healthz, authenticated MCP initialize, 401 on unauthenticated POST).

Directory layout

config/                 sources.yaml (chains / rate limits / redirect allowlist), compliance.yaml (tiers)
src/tickhub_us/
  core/                 settings, errors, HTTP, logging, symbols, DataEnvelope
  cache/                tiered TTL + Redis / in-process LRU fallback
  compliance/           tier registry and interceptor
  providers/            20 source adapters + local indicator computation
  market/               quotes, K-lines, indicators, fund flow, short, volatility, Taiwan
  fundamental/          statements, key metrics, analyst estimates, institutional holders
  options/              options chain, Greeks, 0DTE, unusual flow
  filings/              SEC submissions / XBRL / daily index / full-text / Form 4 / 13F
  mcp/                  MCP server (stdio / HTTP)
  cli/                  th-us command tree
tests/
  contract/             interface contracts + live smoke + defect regressions
  compliance/           compliance interception tests
CHANGELOG.md            update log (the only document in the repository)
SKILL.md                compact agent-facing SOP
Dockerfile              image (non-root, stdio by default)
.github/workflows/      ci.yml (gate) + publish.yml (PyPI / Release) + docker.yml (GHCR)

FAQ

Does it need an API key? No, by default. Only Polygon is an optional source (POLYGON_API_KEY); SEC EDGAR needs a real SEC_CONTACT, which is an identity declaration, not a secret.

Will it silently switch sources when data is missing? It will walk the fallback chain, but it will not degrade around a compliance denial — if every source on the chain is denied, it raises ComplianceError and lists each denial in attempts.

Are HK options available? No. The options layer is US only; HK options would require HKEX's paid proprietary feed.

Can it look up stocks outside the US and HK? K-lines and Yahoo fundamentals, yes: Japan .T, Taiwan .TW, Korea .KS, India .NS, London .L, Germany .DE and more. Note that Yahoo is a tier-D source. Taiwan also has the official TWSE / TPEx APIs (tier S, latest trading day only).

How fresh are global rates and FX? ECB and NY Fed update every business day; Fed H.10 is published each Monday for the prior week; BIS lags by a few days to about three weeks depending on the country. Every value carries a date — check the central bank itself when you need today's exact number.

How often does short interest update? FINRA publishes it twice a month, for settlement dates on the 15th and at month-end (moved earlier for holidays), about 8 business days after settlement. The daily dataset is a different one — daily short volume, which counts that day's short-sale trades, not open short positions.

Can a server in mainland China reach Yahoo / SEC? They are overseas services and may be flaky on a direct connection. Use a proxy, or lean on the Eastmoney / Sina / Tencent sources. The CI live job runs on GitHub-hosted runners, which is why the Eastmoney cases are skipped there.

Can I use it without an MCP client? Yes. The th-us CLI covers every endpoint, and --output json feeds any script directly.

Can I install it from PyPI? Is there a Docker image? Yes to both. pip install tickhub-us installs 1.0.0 (PyPI), the same wheel / sdist ship as v1.0.0 release assets, and the container is public at ghcr.io/quotafuse-ai/tickhub-us (tags 1.0.0 and latest, docker pull needs no login). Publishing is a single manual dispatch of publish.yml / docker.yml; steps are in Publishing.

Version

v1.0.0 (2026-10-26) — first stable release, feature-complete against the spec and re-verified end to end against live sources:

  • Fixed BIS policy rates always returning 404 (the SDMX key duplicated the D. dimension);

  • Fixed Yahoo quoteSummary returning 401 across the board (a non-browser UA got 429, so no crumb could be obtained; now it cools down and retries instead of giving up permanently);

  • Added 13 live smoke cases and a workflow_dispatch live job, with an offline regression test for each of the two defects;

  • Shipped four distribution channels: PyPI wheel / sdist (publish.yml, PEP 639 metadata), GitHub Release assets, GHCR container image (docker.yml, with a real smoke), and source install; the wheel bundles config/, so it runs from any directory. Verified by installing 1.0.0 from PyPI into a clean venv and running a live quote from outside the repository, and by an anonymous docker pull of ghcr.io/quotafuse-ai/tickhub-us:1.0.0.


Disclaimer

This project provides data-access tooling only. It is not investment advice. Markets carry risk. Data licensing follows each source's terms — see config/compliance.yaml.

License

Apache License 2.0. Author: QuotaFuse · https://github.com/QuotaFuse-ai

Update log: CHANGELOG.md · agent SOP: SKILL.md

Related MCP Connectors

  • Real SEC, 13F, insider, congress & macro data your AI agent can cite. Hosted MCP, 24 tools.

    https://mcp.ko.io/mcp
  • Your agent needs markets — prices and fundamentals for listed companies, the filings behind them, crypto, and what the prediction markets put the odds at. **What you can ask for** • "Pull this company's income statement, cash flow and balance sheet for the last 8 quarters." • "What did insiders buy or sell, and when?" • "Snapshot prices for these 50 tickers, then the OHLC history for the three that moved." • "What are the current odds on this event across Kalshi and Polymarket?" • "Screen for companies matching these financial criteria." **How to use it** Point any MCP client at https://mcp.aisa.one/finance/mcp and sign in with OAuth — there is no key to create or paste. 49 tools: prices and snapshots, income statements, balance sheets and cash flows, metrics and ratios, earnings and analyst estimates, filings and line-item search, insider trades, macro interest rates, news, a screener; CoinGecko spot prices, market tables, OHLC, per-venue tickers and trending; Kalshi and Polymarket markets and trades; plus EDINET filings for Japan. **Why this rather than the source** Equities, crypto and event markets behind one account, so a cross-asset question is one conversation. **It is also a door to the rest** The same login reaches 26 sources and 580+ operations. Read the number here, then ask the same agent what X is saying about the ticker today — without adding a second server. **What it costs** Finding and inspecting an operation is free. Running one is billed per call at API prices, with no seat and no monthly minimum, and every call takes max_price_usd so an agent cannot overspend by accident. **Where else it reaches** https://mcp.aisa.one/marketpulse/mcp · /crypto-market-data/mcp · /prediction-market-data/mcp · /stock-pulse/mcp for one slice each.

  • US stock market data for AI agents: SEC filings, financials, insider trades, 13F, options, macro.

    https://mcp.livermore.club/mcp
  • Your agent needs company financials it can compute on — statements, ratios, earnings, estimates, filings and insider activity as structured data, not a PDF. **What you can ask for** • "Give me 8 quarters of income statement, balance sheet and cash flow for this ticker." • "What do analysts estimate for next quarter, and how did the last four surprise?" • "Find this exact line item across every filing." • "Who bought or sold as an insider in the last 90 days?" • "Screen for profitable companies under this valuation with growing revenue." **How to use it** Point any MCP client at https://mcp.aisa.one/marketpulse/mcp and sign in with OAuth — there is no key to create or paste. 21 tools: prices and snapshots, income statements, balance sheets, cash-flow statements, financial metrics and snapshots, earnings, analyst estimates, company facts, filings and filing items, line-item search, a screener, insider trades, macro interest rates, news, plus EDINET documents and filing digests for Japanese issuers. **Why this rather than the source** Statements as fields you can compute on, and a screener in the same place. **It is also a door to the rest** The same login reaches 26 sources and 580+ operations. Read the fundamentals here, then ask the same agent what social is saying about the ticker — without adding a second server. **What it costs** Finding and inspecting an operation is free. Running one is billed per call at API prices, with no seat and no monthly minimum, and every call takes max_price_usd so an agent cannot overspend by accident. **Where else it reaches** https://mcp.aisa.one/finance/mcp for equities, crypto and prediction markets in one place.

Related MCP Servers

  • F
    license
    Not graded
    quality
    A
    maintenance
    Enables AI agents and backend integrations to access standardized market data, technical indicators, fundamentals, news, filings, money-flow analysis, and code-export outputs across A-shares, US equities, ETFs, indices, and crypto. It exposes these capabilities through MCP tools and HTTP APIs.
    -
  • F
    license
    Not graded
    quality
    A
    maintenance
    Enables AI agents and backend workflows to access standardized multi-market financial data, technical indicators, fundamentals, news, filings, money flow, and CSV/JSON exports through MCP tools and HTTP endpoints.
    -
  • F
    license
    Not graded
    quality
    A
    maintenance
    Enables AI agents and backends to access standardized financial market data and analysis tools across A-shares, US equities, ETFs, indices, and crypto, including technical indicators, fundamentals, news, filings, and money flow. It exposes these capabilities through MCP tools and HTTP endpoints, with agent-friendly artifacts and CSV/JSON exports.
    -
  • F
    license
    Not graded
    quality
    A
    maintenance
    Enables AI agents and applications to access and analyze A-share, US equity, ETF, index, and crypto market data, including technical indicators, fundamentals, news, filings, money flow, and exportable CSV/JSON datasets through MCP tools and HTTP APIs.
    -