CLI tool
zvtvz/zvt avatar
zvtvz/zvt

zvt: a modular Python quant framework built around one shared data schema

modular quant framework.

4,312 stars1,015 forksPythonMIT

At a glance

What is it?
zvt is a Python framework that unifies market data capture, storage, querying, factor computation and backtesting behind a single entity model. It is aimed at developers who want to write their own strategies in an IDE and inspect the results in a bundled Dash UI.
Who is it for?
zvt fits developers who want a single Python codebase for data capture, persistence, factor computation and backtesting, and who are willing to read the source when the docs run out.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 94 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 3, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem zvt solves: one schema across capture, storage and study

Most quant side projects rot at the seams. A scraper writes CSV files, a notebook reads them, a backtester expects a different column order, and the factor code invents a third naming convention. zvt's answer is to make the domain model the integration point. Entities such as Stock, Stockus and Stock1dHfqKdata are declared once, and every layer above them, including record_data, query_data, the factor system and the UI, speaks in terms of those declarations. The README frames this as a core design idea: the interface names map one to one onto the system's concepts, which is what makes the framework both uniform and extensible.

The intended user is a developer working alone or in a small team who wants to run research and backtests from an IDE rather than from a hosted platform. The README's own example trains a model, predicts, and draws the result in a handful of lines, and then notes that those lines covered data capture, persistence, incremental update, machine learning, prediction and display. That is the pitch: the wiring between stages is the product, not any single stage.

How the entity and provider layers fit together

Every dataset in zvt is an entity class with a record_data classmethod and a query_data classmethod. record_data takes a provider argument and writes rows into a SQL database through SQLAlchemy; query_data reads them back as a pandas DataFrame. The README shows Stock.record_data(provider="em") followed by Stock.query_data(provider="em", index='code'), and the printed frame carries columns such as id, entity_id, timestamp, entity_type, exchange, code, name, list_date and end_date. The entity_id format is visible in that output: stock_sz_000001, stock_sh_601318, stockus_nyse_A. That string is the join key that ties kdata, factors and signals to the same instrument.

Providers are pluggable by name. "em" appears throughout the README as the eastmoney provider, and the dependency list includes eastmoneypy and jqdatapy, so the provider abstraction is not decorative. Incremental update is handled by record_data itself: the README example passes sleeping_time=1 when recording kdata for several entity ids, which implies the recorder paces its requests rather than firing them all at once. Persistence is not optional. There is a sql directory in the repository root, which is where the schema lives.

Above the data layer sits the factor and signal machinery, and above that a trader concept. The README's screenshots are labelled zvt-factor and zvt-trader, and it says the example depends on data, factor and trader, directing readers to the docs. So the repository confirms the three tiers exist, while the README itself does not spell out the factor API. That gap is the first place a new user will end up in the source.

Installing zvt and running a first data pull

The README gives a single install command from PyPI. Python 3.9 through 3.12 are the declared supported versions in setup.py, and the pinned dependencies include pandas 2.2.3, SQLAlchemy 2.0.36 and pydantic 2.6.4, so an isolated environment is the sane starting point.

bash
python3 -m pip install -U zvt

After installation, the README says to type zvt on the command line. That starts the bundled Dash and Plotly UI, which listens on port 8050 and is meant for backtest and research work rather than live data.

bash
zvt

With the UI up, the next step is to actually record something. The README's data section uses the eastmoney provider directly from a Python session. Recording the full stock list is one call, and querying it back with index='code' gives a frame indexed by ticker.

python
from zvt.domain import Stock, Stock1dHfqKdata

Stock.record_data(provider="em")
df = Stock.query_data(provider="em", index='code')
print(df)

The README's printed output for that query shows 4136 rows and 9 columns, with entries such as 000001 for 平安银行 and 605589 for 圣泉集团. If your run returns a comparable frame, the database, the provider and the entity mapping are all working. From there the README's machine learning example continues with MaStockMLMachine, calling train(), predict() and draw_result() for a chosen entity id.

python
from zvt.ml import MaStockMLMachine

machine = MaStockMLMachine(entity_ids=["stock_sz_000001"], data_provider="em")
machine.train()
machine.predict()
machine.draw_result(entity_id="stock_sz_000001")

For a REST-based setup instead, the README says to install uvicorn, run zvt_server, and open port 8090 for the API docs. That path also expects the tag system to be initialized first by running the scripts under src/zvt/tasks, and the frontend lives in a separate repository, zvt_ui, whose .env file needs NEXT_PUBLIC_SERVER pointed at the zvt_server address.

Where zvt gets in your way

The README carries an unusually blunt declaration: the project does not currently guarantee any backward compatibility, and it advises upgrading with caution. Combined with the note that things once considered important may become less so and may not be maintained, this tells you the maintainer treats the framework as a moving expression of his own workflow. Pinning a version in production is not paranoia here, it is the documented expectation.

The UI split is the second constraint. The README states plainly that the Dash and Plotly UI is good for backtest and research but not applicable for real-time market data and user interaction. Real-time work is pushed to the REST API and the separate zvt_ui frontend, which means a second repository, an environment file, and the task scripts for the tag system before anything appears at port 3000. That is a lot of moving parts for someone who only wants a chart.

Third, the data layer inherits the reliability of its providers. The "em" provider depends on eastmoneypy, an unofficial client for a public site, and the README's own example passes sleeping_time=1 to pace requests. If eastmoney changes a response shape, the failure lands in your recorder, not in a vendor support queue. The README does not document rollback or migration behaviour when a schema changes, and the sql directory is the only visible reference for what the tables should look like.

zvt against a backtest-first library such as backtrader

The closest comparison is with a backtest-first framework like backtrader. The difference is where each one puts the centre of gravity. backtrader is a simulation engine: you feed it data, define a strategy class, and it runs the broker simulation and produces performance statistics. Data acquisition and storage are your problem, and the framework has no opinion about where bars come from.

zvt inverts that. Its entity classes and providers are the foundation, and the backtest, factor and trader layers sit on top of a database that the framework itself fills. The README's opening example is a data capture and persistence example, not a strategy example. If your pain is that your research pipeline is a pile of inconsistent CSV conventions, zvt addresses it directly. If your pain is that you already have clean data and want a battle-tested event loop, zvt's data layer is overhead you did not ask for.

There is also a language and ecosystem difference worth naming. zvt is a Python framework with a pydantic and SQLAlchemy core, so it slots into pandas-based research naturally. That is the same reason its dependency pins are tight: pandas 2.2.3 and numpy 2.1.3 are fixed in requirements.txt, which keeps behaviour predictable but collides with projects that need different versions.

Maintenance, licensing and the cost of upgrading

The repository is not archived and the last push was on 2026-07-01, so the codebase is being touched, though the release cadence is slow: v0.13.3 in August 2025, v0.13.4 in September 2025, and v0.13.5 in January 2026. The version string in setup.py matches v0.13.5, so the package metadata tracks the tag. That cadence matters because the README's no-backward-compatibility declaration means an upgrade is a code review, not a routine bump. Budget time for reading the diff between your pinned version and the target, especially around entity fields and provider behaviour.

The licence is MIT, declared both in the repository and in the setup.py classifier. MIT permits commercial use and modification, and it requires that the copyright notice and permission notice be preserved in copies. This article is not legal advice; if you redistribute zvt inside a product, read the LICENSE file in the repository root and take your own counsel.

One dependency worth flagging on the licence side: the project pins jqdatapy, a client for JoinQuant, alongside eastmoneypy. Those are separate services with their own terms, and zvt's MIT licence says nothing about your right to use them. The framework code and the data sources are two different questions.

Editorial conclusion

zvt fits developers who want a single Python codebase for data capture, persistence, factor computation and backtesting, and who are willing to read the source when the docs run out. It does not fit anyone who needs a stable API across upgrades, since the README states the project does not guarantee backward compatibility, or anyone who needs a mature real-time trading loop, since the Dash UI is described as unsuitable for real-time data and the REST path requires running task scripts and a separate frontend repository. Before committing, verify that the eastmoney provider still returns the fields your strategy needs, and check whether the tables you intend to query exist in the project's sql directory.

Frequently asked questions

How do I install zvt?

Install it from PyPI with python3 -m pip install -U zvt. The supported Python versions declared in setup.py are 3.9 through 3.12. After installation, the README says to run the zvt command, which opens the Dash UI on port 8050.

Does zvt work for real-time trading?

The README states that the Dash and Plotly UI is good for backtest and research but not applicable for real-time market data and user interaction. Real-time use is directed to the REST API path: install uvicorn, run zvt_server, and open port 8090 for the API docs.

Which data providers does zvt support?

The README uses provider="em" (eastmoney) for stock and kdata recording, and the dependency list also includes jqdatapy. Providers are selected by name in the record_data and query_data calls.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. zvtvz/zvt on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/zvtvz-zvt.svg)](https://hysenlabs.com/projects/zvtvz-zvt)