Skip to main content

jing

jing is a Python library for downloading stock price data to local CSV files and organizing market data.

Installation

pip install jing

All required dependencies (requests, pandas, baostock, yfinance, akshare, pyarrow) will be installed automatically.

Quickstart

import jing

# Download AAPL data to local CSV
jing.D('us').download('AAPL')

Main APIs

The core workflow uses the D class for downloading market data:

Class Purpose Network? Typical Use
D Download market data Yes (API calls) Fetch one stock or a batch list to local CSV

D — Downloader

Download stock data from Yahoo Finance, BaoStock, or AkShare into local CSV files.

import jing

# US stock via Yahoo Finance
d = jing.D('us')
d.download('AAPL')

# CN stock via BaoStock (default source for CN)
d = jing.D('cn')
d.download('sz.000807')

# HK stock via AkShare
d = jing.D('hk')
d.download('00700')

# Batch download all stocks in the default CN BaoStock list
d = jing.D('cn')
d.download()  # downloads all stocks in ~/data/jing/list/cn_baostock.txt

# Batch download CN via AkShare instead
d = jing.D('cn', _source='akshare')
d.download()  # downloads all stocks in ~/data/jing/list/cn_ak.txt

Data Storage

The project uses a source-first layout under ~/data/jing/ (override with JING_DATA env var):

~/data/jing/
  raw/
    yahoo/us/
    baostock/cn/
    akshare/cn/
    akshare/hk/
  list/
    us.txt
    cn_ak.txt
    cn_baostock.txt
    hk.txt

Raw CSV examples:

  • US Yahoo CSV: ~/data/jing/raw/yahoo/us/AAPL.csv
  • CN BaoStock CSV: ~/data/jing/raw/baostock/cn/sh.601088.csv
  • HK AkShare CSV: ~/data/jing/raw/akshare/hk/00700.csv

List files

List files are used only for batch downloads, for example jing.D('us').download() or jing.D('cn').download(). Single-stock downloads use the code you pass directly.

On first use, jing creates ~/data/jing/list/ and copies the bundled default lists there. Edit the files under ~/data/jing/list/; do not edit the package files under jing/lists/ unless you are changing the project defaults.

Market/source Downloader call List file Code format
US Yahoo jing.D('us') us.txt Yahoo ticker, e.g. AAPL
CN BaoStock (default CN) jing.D('cn') cn_baostock.txt BaoStock code with exchange prefix, e.g. sh.601088 or sz.000807
CN AkShare jing.D('cn', _source='akshare') cn_ak.txt 6-digit A-share code, e.g. 601088
HK AkShare jing.D('hk') hk.txt 5-digit HK code, e.g. 00700

For CN, use cn_baostock.txt unless you explicitly pass _source='akshare'. The default jing.D('cn') downloader is BaoStock, and BaoStock requires exchange-prefixed codes.

Minimal examples:

~/data/jing/list/cn_baostock.txt

sh.601088
sz.000807
sh.600519

~/data/jing/list/cn_ak.txt

601088
000807
600519

~/data/jing/list/us.txt

AAPL
MSFT
NVDA

~/data/jing/list/hk.txt

00700
09988
03690

Batch download calls:

import jing

jing.D('cn').download()                       # reads cn_baostock.txt
jing.D('cn', _source='akshare').download()    # reads cn_ak.txt
jing.D('us').download()                       # reads us.txt
jing.D('hk').download()                       # reads hk.txt

Download cache

Downloaded data is cached as Parquet files to avoid repeated API calls on the same day:

~/.cache/jing/data/
  cn_baostock_sz_000807_2025-05-25.parquet
  us_yahoo_AAPL_2025-05-25.parquet

Cache pattern: <market>_<source>_<code>_<date>.parquet

  • If cache exists for today → read from Parquet (fast, ~0.01s)
  • If no cache → download from API, save CSV, and write Parquet cache
  • New day → automatic fresh download (old cache ignored)
  • Override the cache root with JING_CACHE

Data flow

Single stock

flowchart LR
    A["d.download('AAPL')"] --> B{Cache exists?}
    B -->|Yes| C[Read Parquet]
    B -->|No| D[Download from API]
    D --> E[Save CSV]
    E --> F[Write Parquet cache]
    C --> G[Return DataFrame]
    F --> G

Batch download

flowchart LR
    A["d.download()"] --> B[Read stock list]
    B --> C[Queue stocks]
    C --> D[Download each]
    D --> E[Print summary]

Incremental Download

jing supports smart incremental downloads to save time and reduce API calls. When you already have historical data locally, jing will:

  1. Fetch only new data plus an overlap period (default 5 days)
  2. Check if the overlapping data matches your local CSV
  3. If consistent → merge the new data
  4. If inconsistent (e.g., due to dividend/split adjustments) → automatically perform a full refresh
import jing

d = jing.D('us')

# Default: smart incremental download
d.download('AAPL')

# Force full refresh
d.download('AAPL', incremental=False)

# Custom overlap days and tolerance
d.download('AAPL', overlap_days=10, tolerance=0.002)

Parameters:

Parameter Default Description
incremental True Enable incremental download
overlap_days 5 Days to overlap for consistency check
tolerance 0.001 Price difference tolerance (0.1%)

Why overlap days?

Stock prices are adjusted for dividends and splits. When these events occur, historical prices change. By overlapping a few days and comparing, jing can detect if adjustments have occurred and automatically refresh the entire history to maintain data consistency.

Incremental download flow

flowchart TD
    A[download\('AAPL'\)] --> B{Local CSV exists?}
    B -->|No| C[Full download]
    B -->|Yes| D[Fetch from last date - 5 days]
    D --> E{Overlapping data consistent?}
    E -->|No| C
    E -->|Yes| F[Merge new data]
    C --> G[Save CSV]
    F --> G

Resuming an interrupted batch download

Batch downloads of a full market (the CN list has ~5,600 codes) are often interrupted by rate limiting. Re-running used to re-query every code, which just hit the rate limit again and never finished the tail.

Resume is on by default: a batch run only queries the codes whose local data is not yet current.

import jing

d = jing.D('cn')

d.download()               # first run: downloads everything; gets rate limited partway
d.download()               # re-run: only downloads what is still missing
d.download(resume=False)   # force: re-query every code in the list

How "already done" is decided

There is no state file to get stale — the local CSVs are the ledger:

  1. Once per run, jing downloads one benchmark symbol to learn the market's latest trading date (1 API call, and usually free because the benchmark is normally already cached that day):

    Market/source Benchmark
    us Yahoo AAPL
    cn BaoStock sh.000001
    cn AkShare 600519
    hk AkShare 00700
  2. Every code in the list has its local CSV's last date checked. If it already reaches that date, the code is skipped; otherwise it is downloaded.

The batch summary reports how many were skipped:

最新交易日: 2026-08-31,本地数据已到达该日期的股票将被跳过
断点续传:跳过 4821 个(已是最新),剩余 854 个待下载

==================================================
           下载结果汇总
==================================================
  总计任务: 5675
  跳过(已是最新): 4821
  本次下载: 854
  ...

To use a different reference symbol, edit BENCHMARK_CODE in jing/resume.py. Any actively traded symbol of that market works, since they all share one trading calendar.

Parameters

Parameter Default Description
resume True Skip codes whose local data is already up to date. Batch downloads only.
incremental True Per-code incremental download (see above).

Notes:

  • resume is ignored when you download a single code: d.download('AAPL') always runs, since you asked for that stock explicitly.
  • resume is disabled when incremental=False, because forcing a full refresh contradicts skipping.
  • If the benchmark probe fails, resume is switched off for that run and everything is downloaded as before — a failed probe never causes missing data.
  • A suspended, delisted or lagging stock never looks "up to date", so it costs one query per run. It heals itself as soon as the stock trades again.

Configuration

Data directory

Priority (highest first):

  1. Function call — programmatic override

    from jing.data_paths import set_data_root
    set_data_root('/custom/data/path')
    
  2. Environment variable

    export JING_DATA=/custom/data/path
    
  3. Default — ~/data/jing

Release to PyPI

  1. Bump the version in pyproject.toml:

    version = "0.3.9"
    
  2. Build the distribution packages:

    python -m build
    
  3. Upload to PyPI:

    python -m twine upload dist/*
    

    You will need a PyPI account and API token. Configure twine once with python -m twine upload --repository testpypi dist/* to test first if desired.

Metadata

Release files for jing 0.3.13

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jing 0.3.13
File Size Uploaded
jing-0.3.13.tar.gz 73.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for jing 0.3.13
File Interpreter ABI Platform
jing-0.3.13-py3-none-any.whl Python 3 none any Details

Total release size: 149.8 kB

Release files / jing-0.3.13.tar.gz

Download URL jing-0.3.13.tar.gz
Size 73.8 kB
Tags Source
SHA-256 checksum
How to use checksums
412928c76d155e910aeb1ab59640f2887c54c90ae9cf4f670eb8db8369a80f09
BLAKE2b-256 checksum
How to use checksums
5b702433653f1d40a63980fe7e145a763cdcbd2f8f297833141d8186b0540de9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.8

Release files / jing-0.3.13-py3-none-any.whl

Download URL jing-0.3.13-py3-none-any.whl
Size 76.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
da6f46fa0c4dee70ca8238a66d178668bc4562a9277869a713e4097610def8f5
BLAKE2b-256 checksum
How to use checksums
16c6fbf94e84f785df9cdbb09239a660adae30a30120de6a53a77a19ec4ced7d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.8

Release history Release notifications | RSS feed

0.6.1

2 release files

0.6.0

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.15

2 release files

0.3.14

2 release files

This release

0.3.13 This release

2 release files

0.3.10

2 release files

0.3.9

2 release files

0.3.8

2 release files

0.3.7

2 release files

0.3.6

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.9

2 release files

0.2.8

2 release files

0.2.7

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.9

2 release files

0.1.8

2 release files

0.1.7

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

0.0.9

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page