libfinance#
[ English | 中文 ]
Conclusions in quantitative research rest on historical data, and historical data is distorted in three common ways: security codes are renamed, reused, and collide across markets; financial statements are revised after release, so a backtest that reads the latest version uses information nobody had at the time; and corporate actions such as dividends and splits break price comparability, so inconsistent adjustment distorts returns. Research and production also tend to run in different languages, Python and C++, and small differences between two interfaces make the same strategy produce different results once it is ported.
libfinance is a financial data client for quantitative research and backtesting, covering Chinese A-shares and US equities, with implementations in Python and C++. It organizes prices, the security catalog, trading calendars, corporate actions, shares, financials, industry / index / theme constituents and daily factors around unified security identifiers, point-in-time data versions and event-by-event adjustment factors. Both markets and both languages follow one interface contract: queries are written the same way, and differences come only from the data.
The data design rests on four conventions:
Unified security identifiers:
<trading_code>.<namespace>, such as600000.XSHG,000001.XSHEandAAPL.US. The namespace separates equal codes in different markets, and codes resolve at a point in time, so renames and reused codes never land on another security.Point-in-time queries with as_of: rebuild the security universe of a past date and select the financial statements disclosed by then, avoiding look-ahead and survivorship bias.
High-quality adjustment factors, exfactor: computed event by event from corporate actions, with unadjusted, forward-adjusted and backward-adjusted prices;
get_ex_factorreturns each event’s factor and the cumulative factor, so every adjustment can be traced.One function design for Python and C++: both clients implement one contract – function names, parameter order and defaults, validation and errors, returned columns; the same calls are sent through both clients to one server and compared item by item.
See Unified security identifiers <trading_code>.<namespace>, Point-in-time mechanism: as_of, High-quality adjustment factors: exfactor and One function design for Python and C++.
from libfinance import get_price
# One call, both markets: each code carries its market
bars = get_price(["600000.XSHG", "AAPL.US"], "2024-03-01", "2024-03-05", adjust_type="none")
What this returns and how to read it: Quickstart.
What data is here#
Data |
Markets |
Main function |
Notes |
|---|---|---|---|
Trading calendar |
CN · US |
Sessions, ranges, N sessions forward or back |
|
Security master |
CN · US |
Code, name, type, listing and delisting dates |
|
Daily bars |
CN · US |
OHLC, volume, turnover; adjustable |
|
Adjustment factors |
CN · US |
Event and cumulative factors by ex-date |
|
Share capital |
CN · US |
Per-session total and floating shares |
|
Dividends / splits / allotments |
CN · US |
Ex-rights events — the source of price gaps; allotments are China only |
|
Spin-offs |
US |
A-shares do not produce this kind of event |
|
Financial statements (PIT) |
CN · US |
Quarterly, with full revision history |
|
Financial metrics |
CN · US |
Derived financial metrics, per trading day |
|
Industry classification |
CN · US |
Shenwan, GICS and more; members and weights via |
|
Index constituents |
CN · US |
CSI, S&P and more; weights via |
|
Themes |
CN |
THS themes; weights via |
|
Daily factors |
CN |
alpha158, qlib, Barra CNE5 style / industry factors, CNE5 and CNE6 descriptors; see Factor data and Factor dictionary |
|
Live quotes |
CN |
Streaming subscription |
How far back the history goes and how recent it is depend on the service you connect to. Do not copy dates out of these docs — ask the service, as shown in How recent the data is.
Where to start#
Install, connect, run your first query. Then read Fetching the last N sessions, which walks through every trap in “give me the last N sessions”.
Start with Point-in-time mechanism: as_of and High-quality adjustment factors: exfactor. Together they decide whether your backtest sees numbers that did not exist at the time.
Snapshot queries and streaming subscriptions are two different paths. Receiving live quotes has a program you can run as-is.
Already using it and something looks wrong? Go straight to Troubleshooting — it is organised by symptom.
Three things worth knowing up front#
These are not advanced topics. They are defaults. Not knowing them means your code runs fine and your numbers are wrong.
Without adjust_type, you get forward-adjusted prices
Same stock, same day: forward-adjusted close 8.81, unadjusted 10.49 — a 16%
difference. Use adjust_type to select the price convention explicitly.
See Prices and adjustment.
end_date cannot be today
The calendar is published ahead of time (it reaches the end of the year); price data only reaches the last closed session. Passing today is rejected outright rather than silently returning a shorter table. See How recent the data is.
Financial statements get restated
One company’s Q2 2024 net profit exists here in five versions, the latest
published in 2026. Omit as_of in a backtest and you are using numbers
from the future. See Restatements and as_of.