当前位置:首页>行情>Baostock 获取中国 A 股行情及财务数据

Baostock 获取中国 A 股行情及财务数据

  • 2026-10-22 15:33:30
Baostock 获取中国 A 股行情及财务数据

Baostock 获取中国 A 股数据教程

提示

这个文档源于我的课程中的教学资料,源文件为 Jupyter Notebook格式,发布在公众号主要是测试 VSCode 插件QMD2Any的功能。该插件指在实现在VSCode中将 Quarto / Markdown / R Markdown / Notebook 等格式文件一键导出公众号 & 知乎中。

教程目标

本教程目标是让你从零开始学会使用 Baostock 获取中国 A 股历史行情与部分财务数据,并完成基础分析。

学习完成后,你应能: 1. 理解 Baostock 的基本使用流程。 2. 获取 A 股股票列表与单只股票历史 K 线数据。 3. 使用 pandas 进行基础清洗与统计。 4. 画出收盘价走势图并保存数据到本地。

为什么选用 Baostock?

像 Akshare 这样的数据接口也可以获取 A 股数据,并且非常流行。但是Akshare 本质上是一个数据抓取工具,现在的趋势是各数据源反爬虫措施越来越严格,很容易出现接口失效的情况。而 Tushare Pro 需要注册并获取 token,基本上需要付费才能正常使用。相比之下,Baostock 是一个免费的 A 股数据接口,不依赖爬虫,数据源稳定,且无需注册即可免费使用,非常适合初学者。

一、安装baostock

# 如果你还没安装依赖,请先取消下一行注释后运行# !pip install baostock-i https://pypi.tuna.tsinghua.edu.cn/simpleimport sysprint("Python版本:", sys.version)
Python版本: 3.12.12 | packaged by Anaconda, Inc. | (main, Oct 21 2025, 20:05:38) [MSC v.1929 64 bit (AMD64)]
import baostock as bsimport pandas as pdimport matplotlib.pyplot as pltprint("库导入成功")
库导入成功

二、登录 Baostock

使用 Baostock 前必须先登录。

  • 成功时 error_code 一般为 0。
  • 出错时请检查网络,或稍后重试。
lg = bs.login()print("login respond error_code:", lg.error_code)print("login respond  error_msg:", lg.error_msg)
login success!login respond error_code: 0login respond  error_msg: success

登录成功后,将通过具体的案例说明如何使用 Baostock 获取 A 股数据。

三、获取某日全部股票列表

先获取某个交易日的 A 股列表,方便后续选择股票代码。

说明: - sh 表示上交所,sz 表示深交所。 - 股票代码格式类似sh.600000、sz.000001。

rs = bs.query_all_stock(day="2026-7-24")data_list = []while (rs.error_code == "0") and rs.next():    data_list.append(rs.get_row_data())stock_df = pd.DataFrame(data_list, columns=rs.fields)print("股票数量:", len(stock_df))stock_df.head(10)
股票数量: 7315
code
tradeStatus
code_name
0
sh.000001
1
上证综合指数
1
sh.000002
1
上证A股指数
2
sh.000003
1
上证B股指数
3
sh.000004
1
上证工业类指数
4
sh.000005
1
上证商业类指数
5
sh.000006
1
上证房地产指数
6
sh.000007
1
上证公用事业指数
7
sh.000008
1
上证综合业类指数
8
sh.000009
1
上证380
9
sh.000010
1
上证180指数

四、获取单只股票历史日 K 线

下面以浦发银行 sh.600000 为例,获取 2023-01-01 到 2023-12-31 的日线数据。

字段解释(重点): - date: 交易日期 - open/high/low/close: 开高低收 - volume: 成交量 - amount: 成交额 - turn: 换手率 - pctChg: 涨跌幅(%) - peTTM: 滚动市盈率

什么是复权?

在股票历史数据中,分红、送股、配股会让价格出现“跳变”。 如果不处理,直接看长期走势会产生误解,所以常用“复权”来把历史价格放到可比口径。

  • 不复权:保留当时市场真实成交价格。
  • 前复权:以“当前价格体系”为基准,向前调整历史价格。常用于看长期技术走势。
  • 后复权:以“历史价格体系”为基准,向后调整近期价格。常用于研究长期累计收益。

在 Baostock 的 query_history_k_data_plus 中,通常使用 adjustflag控制:

  • adjustflag="1"
    :后复权
  • adjustflag="2"
    :前复权
  • adjustflag="3"
    :不复权(原始价格口径)

当前代码使用的是adjustflag="2",因此拿到的是前复权口径,不是原始不复权价格。

query_history_k_data_plus 常用重要参数

函数原型(简化):query_history_k_data_plus(code, fields, start_date, end_date, frequency, adjustflag)

  • code
    :证券代码
    • 示例:"sh.600000"、"sz.000001"
    • 作用:指定查询哪只股票 / 指数。
  • fields
    :返回字段列表(逗号分隔)
    • 示例:"date,open,high,low,close,volume,amount,turn,pctChg,peTTM"
    • 作用:控制返回哪些列;字段越多,数据越全,处理也更重。
  • start_date
     与 end_date:日期区间
    • 格式:"YYYY-MM-DD"
    • 作用:限定时间范围;若区间无交易日,结果可能为空。
  • frequency
    :K 线周期
    • "d"
      :日线
    • "w"
      :周线
    • "m"
      :月线
    • "5"
      、"15"、"30"、"60":分钟线(具体可用范围以接口实际支持为准)
    • 作用:决定每条记录的时间粒度。
  • adjustflag
    :复权方式
    • "1"
       后复权,"2" 前复权,"3" 不复权
    • 作用:决定价格口径,直接影响开高低收、涨跌幅等分析结果。

实务中怎么选参数

  • 做回测或还原当时交易价格:优先 adjustflag="3"(不复权)。
  • 做技术形态观察、画长期趋势线:常用 adjustflag="2"(前复权)。
  • 做长期收益复盘:可尝试adjustflag="1"(后复权),并与不复权结果交叉验证。

建议:同一份分析报告中保持复权口径一致,并在图表标题或注释中明确写出“前复权 / 后复权 / 不复权”。

code = "sh.600000"fields = "date,open,high,low,close,volume,amount,turn,pctChg,peTTM"rs = bs.query_history_k_data_plus(    code=code,    fields=fields,    start_date="2023-01-01",    end_date="2023-12-31",    frequency="d",    adjustflag="2",)data_list = []while (rs.error_code == "0") and rs.next():    data_list.append(rs.get_row_data())k_df = pd.DataFrame(data_list, columns=rs.fields)k_df.head()
date
open
high
low
close
volume
amount
turn
pctChg
peTTM
0
2023-01-03
6.2189106700
6.2274648800
6.1333685700
6.1846938300
25892521
187094064.4100
0.088200
-0.686800
4.086661
1
2023-01-04
6.2189106700
6.2873443500
6.1846938300
6.2531275100
30947081
226321372.0500
0.105400
1.106500
4.131880
2
2023-01-05
6.3044527700
6.3130069800
6.2445733000
6.2873443500
30162154
221617354.6200
0.102800
0.547200
4.154489
3
2023-01-06
6.2873443500
6.3130069800
6.2531275100
6.2787901400
20312881
149170537.8500
0.069200
-0.136100
4.148837
4
2023-01-09
6.3130069800
6.3130069800
6.2445733000
6.2787901400
19612260
143998210.6000
0.066800
0.000000
4.148837
k_df.info()
<class 'pandas.core.frame.DataFrame'>RangeIndex: 242 entries, 0 to 241Data columns (total 10 columns): #   Column  Non-Null Count  Dtype ---  ------  --------------  -----  0   date    242 non-null    object 1   open    242 non-null    object 2   high    242 non-null    object 3   low     242 non-null    object 4   close   242 non-null    object 5   volume  242 non-null    object 6   amount  242 non-null    object 7   turn    242 non-null    object 8   pctChg  242 non-null    object 9   peTTM   242 non-null    objectdtypes: object(10)memory usage: 19.0+ KB

五、数据清洗与类型转换

刚下载的数据大多数是字符串类型,需要转换为数值和日期,才能做统计和画图。

k_df["date"] = pd.to_datetime(k_df["date"])num_cols = ["open","high","low","close","volume","amount","turn","pctChg","peTTM",]for c in num_cols:    k_df[c] = pd.to_numeric(k_df[c], errors="coerce")print(k_df.dtypes)print("缺失值统计:")print(k_df.isna().sum())k_df.describe()
date      datetime64[ns]open             float64high             float64low              float64close            float64volume             int64amount           float64turn             float64pctChg           float64peTTM            float64dtype: object缺失值统计:date      0open      0high      0low       0close     0volume    0amount    0turn      0pctChg    0peTTM     0dtype: int64
date
open
high
low
close
volume
amount
turn
pctChg
peTTM
count
242
242.000000
242.000000
242.000000
242.000000
2.420000e+02
2.420000e+02
242.000000
242.000000
242.000000
mean
2023-07-04 08:43:38.181818112
6.270547
6.311260
6.226810
6.265696
2.794742e+07
2.024940e+08
0.095212
-0.016855
4.564916
min
2023-01-03 00:00:00
5.828724
5.891302
5.801904
5.837663
1.089596e+07
7.832138e+07
0.037100
-3.266300
3.967961
25%
2023-04-04 12:00:00
6.167585
6.196891
6.132675
6.159147
1.900229e+07
1.358189e+08
0.064725
-0.544750
4.155534
50%
2023-07-05 12:00:00
6.251010
6.287344
6.218911
6.248892
2.454976e+07
1.723911e+08
0.083650
0.000000
4.583388
75%
2023-09-27 18:00:00
6.355778
6.396894
6.311471
6.347230
3.118753e+07
2.240860e+08
0.106275
0.515350
4.741525
max
2023-12-29 00:00:00
6.963127
7.031561
6.792043
6.903247
1.431179e+08
1.148390e+09
0.487600
3.994800
5.279523
std
NaN
0.187525
0.196621
0.177304
0.187503
1.573174e+07
1.233238e+08
0.053596
0.917957
0.367745

六、可视化:收盘价走势图

通过折线图观察股票价格随时间的变化趋势。

plt.rcParams["font.sans-serif"] = ["SimHei", "Microsoft YaHei", "Arial Unicode MS"]plt.rcParams["axes.unicode_minus"] = Falseplt.figure(figsize=(12, 5))plt.plot(k_df["date"], k_df["close"], label=f"{code} 收盘价")plt.title("2023年收盘价走势")plt.xlabel("日期")plt.ylabel("收盘价")plt.grid(alpha=0.3)plt.legend()plt.show()

七、拓展:和上证指数做对比

在股市中我们经常比较个股和大盘表现。这里用上证指数 sh.000001做简单对比。

步骤: 1. 获取指数收盘价 2. 计算累计收益率 3. 画图比较

获取指数数据时要复权吗?

对于指数数据,通常不需要复权,因为指数本身已经考虑了成分股的分红、送股等因素。

index_rs = bs.query_history_k_data_plus(    code="sh.000001",    fields="date,close",    start_date="2023-01-01",    end_date="2023-12-31",    frequency="d",    adjustflag="3",)index_list = []while (index_rs.error_code == "0") and index_rs.next():    index_list.append(index_rs.get_row_data())index_df = pd.DataFrame(index_list, columns=index_rs.fields)index_df["date"] = pd.to_datetime(index_df["date"])index_df["close"] = pd.to_numeric(index_df["close"], errors="coerce")compare_df = pd.merge(    k_df[["date", "close"]].rename(columns={"close": "stock_close"}),    index_df[["date", "close"]].rename(columns={"close": "index_close"}),    on="date",    how="inner",)compare_df["stock_return"] = (    compare_df["stock_close"] / compare_df["stock_close"].iloc[0] - 1)compare_df["index_return"] = (    compare_df["index_close"] / compare_df["index_close"].iloc[0] - 1)plt.figure(figsize=(12, 5))plt.plot(compare_df["date"], compare_df["stock_return"], label="个股累计收益率")plt.plot(compare_df["date"], compare_df["index_return"], label="上证指数累计收益率")plt.title("个股与大盘累计收益率对比(2023)")plt.xlabel("日期")plt.ylabel("累计收益率")plt.grid(alpha=0.3)plt.legend()plt.show()

八、获取财务数据示例

Baostock 还支持部分财务数据。下面演示获取利润数据(示例:2023 年一季度)。

注意:财务数据接口字段较多,不同年份可能有缺失,属于正常现象。

profit_rs = bs.query_profit_data(code="sh.600000", year=2023, quarter=1)profit_list = []while (profit_rs.error_code == "0") and profit_rs.next():    profit_list.append(profit_rs.get_row_data())profit_df = pd.DataFrame(profit_list, columns=profit_rs.fields)profit_df
code
pubDate
statDate
roeAvg
npMargin
gpMargin
netProfit
epsTTM
MBRevenue
totalShare
liqaShare
0
sh.600000
2023-04-29
2023-03-31
0.022428
0.335905
16150000000.000000
1.622163
29352174759.00
29352174759.00

九、保存数据到本地

数据分析项目通常需要把结果保存为 CSV,方便后续汇报、建模或共享。

import ossave_dir = "output"os.makedirs(save_dir, exist_ok=True)k_path = os.path.join(save_dir, "sh600000_kdata_2023.csv")c_path = os.path.join(save_dir, "compare_stock_index_2023.csv")p_path = os.path.join(save_dir, "sh600000_profit_2023q1.csv")k_df.to_csv(k_path, index=False, encoding="utf-8-sig")compare_df.to_csv(c_path, index=False, encoding="utf-8-sig")profit_df.to_csv(p_path, index=False, encoding="utf-8-sig")print("已保存文件:")print(k_path)print(c_path)print(p_path)
已保存文件:output\sh600000_kdata_2023.csvoutput\compare_stock_index_2023.csvoutput\sh600000_profit_2023q1.csv
# 使用结束后,记得登出bs.logout()
logout success!<baostock.data.resultset.ResultData at 0x1ca89f79ca0>

总结

如果有使用过 Tushare Pro 或 Akshare 的同学,应该能明显感受到 Baostock 读取数据的时候相对而言更加繁琐。所以,后续如果要建一步使用,建议将自己常用的读取步骤封装成函数,或者写成一个类,方便后续调用。

最新文章

随机文章