Baostock
Baostock is a Python library designed to provide free historical data for the China stock market, sourced from Baostock.com. It allows users to retrieve various types of data, including daily K-line data, stock basic information, and transaction details, making it a valuable tool for quantitative analysis and research. The current version is 0.9.1, and releases typically occur to fix bugs or adapt to changes in the Baostock data service.
Common errors
-
Login failed! Code: 10001, Msg: User name or password error!
cause Incorrect username or password provided during `bs.login()`.fixDouble-check your Baostock account credentials. Ensure no leading/trailing spaces or typos. If using environment variables, verify they are correctly set. -
_bs_client is not login!
cause An attempt was made to query data (e.g., `bs.query_history_k_data_plus()`) before successfully logging into the Baostock service with `bs.login()`.fixEnsure `bs.login()` is called and returns a successful response (`lg.error_code == '0'`) before attempting any data retrieval operations. -
requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer'))cause Network issues, firewall blocking, or the Baostock server prematurely closing the connection. This can also happen if the server is under heavy load or temporarily down.fixCheck your internet connection and firewall settings. Try again after some time. If persistent, this might indicate a problem with the Baostock service itself or a transient network issue between you and the server. -
DataFrame is empty after query, e.g., print(result.empty) -> True
cause No data was returned for the specified stock code, date range, or query parameters. This often happens for delisted stocks, incorrect stock codes, or periods without available data.fixVerify the stock code is correct (e.g., 'sh.600000' or 'sz.000001'). Adjust the `start_date` and `end_date` to ensure data should exist. Check if the stock was active during the queried period. Ensure `rs.error_code` is '0' before processing `rs.next()`.
Warnings
- gotcha Login failures are common due to incorrect credentials, network issues, or Baostock service instability. Always check the `error_code` and `error_msg` returned by `bs.login()`.
- gotcha Data retrieved for certain tickers or time ranges might be incomplete or empty, especially for delisted stocks or periods far in the past/future. The `query_history_k_data_plus` method does not always raise an error for empty results.
- gotcha The Baostock service might occasionally be slow or unresponsive, leading to connection timeouts or delays. The library's underlying `requests` calls might hang or fail.
- gotcha Repeated, rapid requests can lead to IP-based rate limiting or temporary bans from the Baostock server, causing requests to fail with generic errors or connection issues.
Install
-
pip install baostock
Imports
- baostock
from baostock import login
import baostock as bs
Quickstart
import baostock as bs
import pandas as pd
import os
# Baostock login credentials can be set as environment variables (recommended for production)
# For local testing, replace with actual username/password or remove os.environ.get if hardcoding (not recommended)
USERNAME = os.environ.get('BAOSTOCK_USERNAME', 'your_username')
PASSWORD = os.environ.get('BAOSTOCK_PASSWORD', 'your_password')
if not USERNAME or not PASSWORD or USERNAME == 'your_username':
print("Warning: Please set BAOSTOCK_USERNAME and BAOSTOCK_PASSWORD environment variables or replace placeholders.")
print("Attempting login with placeholder credentials, which will likely fail.")
# Using placeholder for runnable example if env vars not set, but it will likely fail a real login
USERNAME = "PLACEHOLDER_USER"
PASSWORD = "PLACEHOLDER_PASS"
# Login to Baostock service
print("Attempting to log in to Baostock...")
lg = bs.login(USERNAME, PASSWORD)
if lg.error_code == '0':
print(f"Login success! User ID: {lg.uid}")
else:
print(f"Login failed! Code: {lg.error_code}, Msg: {lg.error_msg}")
# For a real application, you might want to exit here: import sys; sys.exit(1)
# Only proceed if login was successful or if you want to test query failure
if lg.error_code == '0':
# Query historical K-data for a stock (e.g., 'sh.600000' for Pudong Development Bank)
# Fields: date,code,open,high,low,close,preclose,volume,amount,adjustflag,turn,tradestatus,pctChg,peTTM,pbMRQ,psTTM,pcfNCM,isST
print("Querying historical K-data for sh.600000...")
rs = bs.query_history_k_data_plus("sh.600000",
"date,code,open,high,low,close,preclose,volume,amount,adjustflag,turn,tradestatus,pctChg,peTTM,pbMRQ,psTTM,pcfNCM,isST",
start_date='2023-01-01', end_date='2023-01-31',
frequency="d", adjustflag="2") # frequency="d" means daily, adjustflag="2" means front-adjust
data_list = []
if rs.error_code == '0':
while rs.next():
data_list.append(rs.get_row_data())
result = pd.DataFrame(data_list, columns=rs.fields)
print("\nSample K-data for sh.600000:")
print(result.head())
# Logout
bs.logout()
print("\nLogout successful.")
else:
print("Skipping data query due to login failure.")