Skip to content

Repository files navigation

xQuant

xQuant is a local, single-user quantitative research application for historical stock data. It combines iTick REST ingestion, durable DuckDB storage, pandas/NumPy and QuantLib analytics, Plotly charts, Streamlit workflows, and JupyterLab research.

Current development release: v0.2. Its versioned product definition is in design/v0.2/; design/v0.1/ remains the immutable first-release baseline.

Dependencies

xQuant requires Python 3.14 and installs its Python dependencies from pyproject.toml:

  • duckdb — durable local market-data storage and SQL analytics.
  • httpx[socks] — iTick REST requests, including optional SOCKS proxy support.
  • pandas, numpy, PyArrow, and pytz — tabular analytics, numerical calculations, CSV/Parquet reference data, and time-zone support.
  • QuantLib — pricing, calendars, curves, and risk analytics.
  • Streamlit — local application interface.
  • Plotly and Kaleido — interactive financial charts and figure export.
  • Pydantic, pydantic-settings, and PyYAML — models and configuration.
  • JupyterLab and ipykernel — notebook-based research.

Development and verification additionally use pytest, pytest-cov, respx, and Ruff. The installation command below installs both runtime and development dependencies; users do not need to install DuckDB or the other packages individually.

Install

Python 3.14 is required. The existing environment can be used:

git clone git@github.com:xtcyclist/xQuant.git
cd xQuant
python3.14 -m venv xQuantEnv
source xQuantEnv/bin/activate
python -m pip install -e ".[dev]"
cp .env.example .env
cp configs.example.json configs.json

Edit the ignored local configs.json and replace the placeholder with your own iTick token:

{"service": "iTick", "token": "replace-with-your-token"}

An exported shell ITICK_TOKEN takes priority over configs.json; configs.json takes priority over .env. Then initialize storage:

xquant init-db

Manage the data universe

xQuant has one durable data universe: the market_bars table in DuckDB. Data Manager adds to or removes from that universe through explicit tasks filtered by market, exchange, stock IDs, temporal frequencies, and inclusive date ranges. Overlapping loads are idempotent and never create duplicate datasets.

xquant sync-metadata

sync-metadata downloads iTick's supported stock IDs, names, regions, and exchanges into DuckDB. Data Manager can perform the same refresh and then provides dependent Region → Exchange → searchable Stock selectors. Cached metadata remains available offline, and failed region refreshes retain their previous catalog.

The virtual China market combines Shanghai (SH/SSE), Shenzhen (SZ/SZSE), Beijing (BJ/BSE), and Hong Kong (HK/HKEX) selections while preserving the source region required by iTick requests. iTick currently returns no Beijing stock symbols; the UI reports this explicitly and will include them automatically if the API adds support. A large filtered task is split into source-specific API requests and may consume substantial API quota.

The Data Manager header reports total DuckDB storage, bar count, stock count, frequency series count, and overall date coverage. Removal tasks preview their matching bar count and require confirmation before permanently deleting data.

The Reference data tab validates and imports the supplied config/sector_classifications.csv snapshot into DuckDB. It reports catalog matches, unclassified rows, market/sector coverage, import provenance, and rejected records. Provider-neutral CSV or Parquet fundamental facts can be added with point-in-time availability timestamps.

Stock Selector can build a market-wide, resumable Parquet snapshot without filling the main DuckDB universe. Snapshots retain complete normalized OHLCV, turnover, source, and ingestion fields under data/selector_snapshots/market=.../interval=.../as_of=.../. Each snapshot freezes its classification mapping, records per-stock progress in DuckDB, and remains available until explicitly removed. Building China-wide history can consume substantial iTick quota; the UI estimates requests and size and requires confirmation. Failed or rate-limited stocks can be resumed without refetching completed members.

Screening reads the selected snapshot with DuckDB Parquet predicate pushdown. Choosing results and selecting Add selected stocks to data universe copies their full bars locally and idempotently into market_bars; this promotion makes no additional iTick request. Selector snapshots and the durable data universe remain separate until that explicit action.

Run the application

xquant app

Open the Streamlit URL shown in the terminal. The application provides:

  • Data Manager for filtered add/remove tasks, storage status, coverage, and logs.
  • Stock Selector for sector-rotation visualization, strict metric screening, DuckDB-backed versioned filter sets, and handoffs to other workflows.
  • Market Explorer for filtering up to five stock IDs at one common frequency, with separate candlesticks, indicators, metrics, and exports for each stock.
  • Research Lab for opening project notebooks in a separate JupyterLab browser tab.
  • Named workspace snapshots for restoring UI, chart, and research-reference state.

Jupyter research

Register this environment once and start JupyterLab:

python -m ipykernel install --user --name xquant --display-name "xQuant (Python 3.14)"
xquant jupyter

Open either starter notebook from Research Lab. Notebook code uses the same xquant package and DuckDB file as the application. Save durable research in cells or move reusable functions into src/xquant; live kernel variables are not part of workspace snapshots.

Storage, backup, and export

The default data/xquant.duckdb is file-backed and durable across restarts. DuckDB uses transactional storage and recovery, but durability is not a backup strategy.

xquant backup
xquant export --directory data/exports

Run a backup when no other xQuant process is writing. Keep external backup copies outside the project machine as appropriate.

Development

ruff check .
pytest

Tests use temporary DuckDB files and mocked iTick responses. A live iTick smoke test is skipped unless explicitly enabled with credentials.

Security and scope

Every user must provide their own iTick token. Real tokens are loaded from environment variables or ignored local configs.json and never belong in source control, example files, workspace state, logs, or notebook URLs. v0.1 covers historical stocks only. Real-time WebSockets, order execution, portfolio accounting, multi-user deployment, and live Jupyter kernel persistence are outside this release.

About

a personal quant analytics system

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages