纯 .NET 9 客户端,对接 baostock 中国 A 股市场数据服务。 完整复刻 baostock Python 客户端的全部公开 API。
🎉 v1.3.4 已发布(2026-04-25,RFC 7233 完全合规 + Actions Node.js 24 升级):416 响应
Content-Range: bytes */<total>完全合规 §4.2 / GitHub Actions 升级(checkout v6 / setup-dotnet v5 / upload-artifact v7 / pages v5)应对 2026-06-02 Node.js 20 弃用 /.gitignore补tmp_*+ 清理 17 文件。零 BREAKING,完全兼容 v1.3.3。v1.3.3 已发布(2026-04-25,v1.3.2 契约缺陷热修):3 个 internal endpoint meta
method修正为 GET //api/multi/*三端点补齐sources字段 //api/cninfo/pdf-downloadRange 完整支持 RFC 7233(bytes=A-B+Content-Range+Accept-Ranges)。零 BREAKING,完全兼容 v1.3.2。v1.3.2 已发布(2026-04-25,API 可观测性优化):HTTP 多源端点响应顶层暴露
sources字段(Bug-N-02) / TestUI PDF 下载支持Range: bytes=N-续传透传(Bug-N-04) //api/meta/endpoints元数据增加method字段(Bug-N-05)。零 BREAKING,完全兼容 v1.3.1。v1.3.1 已发布(2026-04-24,银行字段修复 + 手册补齐):银行/券商利润表
TotalOperateIncome从OperateIncome自动兜底(Finding B-ICBC)/ 手册模块 I 补 I6/I7/I8 创业板/科创板/北交所硬性用例。零 BREAKING,完全兼容 v1.3.0。v1.3.0 发布(2026-04-24,HTTP 多源扩展):财报三表东财 + 新浪双源对冲 / 巨潮公告检索 + PDF 下载(Range 断点续传) / TestUI 新增 5 个端点。零 BREAKING,向后兼容 v1.2.0。 详见 v1.3.0 专集。
v1.2.0 发布(2026-04-24):新增三源实时行情 + 双源历史 K 线 + TCP 自愈 + TestUI 子项目。 包含 4 条 BREAKING CHANGES(代码格式 / 异常类型 / Models 输出 / IsLoggedIn 语义)。 详见 v1.2.0 专集 与 CHANGELOG。
dotnet add package Baostock.NETusing Baostock.NET;
await using var client = await BaostockClient.CreateAndLoginAsync();
// K 线数据(v1.2.0 BREAKING:证券代码默认东方财富风格 SH600000 / SZ000001 / BJ430047,亦兼容 sh.600000、sh600000、600000.SH等格式)
await foreach (var row in client.QueryHistoryKDataPlusAsync("SH600000",
startDate: "2024-01-01", endDate: "2024-01-31"))
{
Console.WriteLine($"{row.Date} {row.Close}");
}
// 财务指标
await foreach (var row in client.QueryProfitDataAsync("SH600000", 2023, 2))
{
Console.WriteLine($"{row.RoeAvg}");
}| Python | .NET | 说明 |
|---|---|---|
bs.login() |
BaostockClient.CreateAndLoginAsync() |
登录(默认匿名) |
bs.logout() |
client.LogoutAsync() |
登出当前会话 |
bs.set_API_key() |
client.Session.ApiKey |
设置 API Key(属性赋值) |
| Python | .NET | 说明 |
|---|---|---|
bs.query_history_k_data_plus() |
client.QueryHistoryKDataPlusAsync() |
K 线数据(日/周/月/分钟) |
| Python | .NET | 说明 |
|---|---|---|
bs.query_profit_data() |
client.QueryProfitDataAsync() |
盈利能力 |
bs.query_operation_data() |
client.QueryOperationDataAsync() |
营运能力 |
bs.query_growth_data() |
client.QueryGrowthDataAsync() |
成长能力 |
bs.query_dupont_data() |
client.QueryDupontDataAsync() |
杜邦指数 |
bs.query_balance_data() |
client.QueryBalanceDataAsync() |
资产负债 |
bs.query_cash_flow_data() |
client.QueryCashFlowDataAsync() |
现金流量 |
| Python | .NET | 说明 |
|---|---|---|
bs.query_dividend_data() |
client.QueryDividendDataAsync() |
股息分红 |
bs.query_adjust_factor() |
client.QueryAdjustFactorAsync() |
复权因子 |
| Python | .NET | 说明 |
|---|---|---|
bs.query_performance_express_report() |
client.QueryPerformanceExpressReportAsync() |
业绩快报 |
bs.query_forecast_report() |
client.QueryForecastReportAsync() |
业绩预告 |
| Python | .NET | 说明 |
|---|---|---|
bs.query_deposit_rate_data() |
client.QueryDepositRateDataAsync() |
存款利率 |
bs.query_loan_rate_data() |
client.QueryLoanRateDataAsync() |
贷款利率 |
bs.query_required_reserve_ratio_data() |
client.QueryRequiredReserveRatioDataAsync() |
存款准备金率 |
bs.query_money_supply_data_month() |
client.QueryMoneySupplyDataMonthAsync() |
货币供应量(月度) |
bs.query_money_supply_data_year() |
client.QueryMoneySupplyDataYearAsync() |
货币供应量(年度) |
| Python | .NET | 说明 |
|---|---|---|
bs.query_trade_dates() |
client.QueryTradeDatesAsync() |
交易日历 |
bs.query_all_stock() |
client.QueryAllStockAsync() |
证券列表(指定日期) |
bs.query_stock_basic() |
client.QueryStockBasicAsync() |
证券基本资料 |
| Python | .NET | 说明 |
|---|---|---|
bs.query_stock_industry() |
client.QueryStockIndustryAsync() |
行业分类 |
bs.query_hs300_stocks() |
client.QueryHs300StocksAsync() |
沪深 300 成分股 |
bs.query_sz50_stocks() |
client.QuerySz50StocksAsync() |
上证 50 成分股 |
bs.query_zz500_stocks() |
client.QueryZz500StocksAsync() |
中证 500 成分股 |
| Python | .NET | 说明 |
|---|---|---|
| — | client.QueryTerminatedStocksAsync() |
终止上市股票 |
| — | client.QuerySuspendedStocksAsync() |
暂停上市股票 |
| — | client.QueryStStocksAsync() |
ST 股票 |
| — | client.QueryStarStStocksAsync() |
*ST 股票 |
| — | client.GetRealtimeQuoteAsync(code) |
实时行情(三源对冲:Sina → Tencent → EastMoney) |
| — | client.GetRealtimeQuotesAsync(codes) |
批量实时行情 |
| — | client.GetHistoryKLineAsync(code, freq, start, end) |
历史 K 线(双源对冲:EastMoney → Tencent) |
// 实时行情:三源对冲(v1.2.0 Sprint 2)
await using var client = await BaostockClient.CreateAndLoginAsync();
var quote = await client.GetRealtimeQuoteAsync("SH600519");
Console.WriteLine($"{quote.Code} {quote.Name} 现价={quote.Last} 昨收={quote.PreClose} 来源={quote.Source}");
// 批量
var quotes = await client.GetRealtimeQuotesAsync(new[] { "SH600519", "SZ000001", "BJ430047" });
// 历史 K 线:双源对冲(v1.2.0 Sprint 2 Phase 2)
// 默认 PreAdjust 前复权;500ms hedge 间隔;EM 不响应或失败时自动切到 Tencent
var rows = await client.GetHistoryKLineAsync(
"SH600519",
KLineFrequency.Day,
DateTime.Today.AddDays(-30),
DateTime.Today);
foreach (var r in rows.Take(3))
Console.WriteLine($"{r.Date:yyyy-MM-dd} O={r.Open} C={r.Close} H={r.High} L={r.Low} 来源={r.Source}");
// 注意:北交所(BJ*)历史 K 线在当前 EM/Tencent 公网端点均不可用,会抛 AllSourcesFailedException;
// Sprint 3 计划接入替代源补齐。详见 CHANGELOG v1.2.0-preview2 Notes。// 财报三表:东财 + 新浪双源对冲(v1.3.0)
using Baostock.NET.Financials;
await using var client = await BaostockClient.CreateAndLoginAsync();
var req = new FinancialStatementRequest("SH600519");
var balance = await client.QueryFullBalanceSheetAsync(req);
foreach (var r in balance.Take(3))
Console.WriteLine($"{r.ReportDate} 总资产={r.TotalAssets:N0} 总负债={r.TotalLiabilities:N0} 来源={r.Source}");
var income = await client.QueryFullIncomeStatementAsync(req);
var cashflow = await client.QueryFullCashFlowAsync(req);// 巨潮公告检索(v1.3.0)
using Baostock.NET.Cninfo;
var cninfoReq = new CninfoAnnouncementRequest(
Code: "SH600519",
Category: CninfoAnnouncementCategory.AnnualReport,
StartDate: new DateOnly(2024, 1, 1),
EndDate: null);
var announcements = await client.QueryAnnouncementsAsync(cninfoReq);
foreach (var a in announcements.Take(5))
Console.WriteLine($"{a.PublishDate} {a.Title} -> {a.FullPdfUrl}");// 巨潮 PDF 下载(支持断点续传)(v1.3.0)
var first = announcements[0];
// 方式 A:流式读到内存 / 上游管道
await using (var pdfStream = await client.DownloadPdfAsync(first.AdjunctUrl))
{
// 透传、上传、入库……
}
// 方式 B:直接落盘;resume=true 时按已存在文件大小发起 Range 续传
var bytes = await client.DownloadPdfToFileAsync(
first.AdjunctUrl,
destinationPath: $"./pdf/{first.AnnouncementId}.pdf",
resume: true);
Console.WriteLine($"written: {bytes} bytes");- 纯 .NET 9 — 无 Python 依赖、无 IPC、无嵌入解释器
- async/await — 全异步,
IAsyncEnumerable<T>流式返回大结果集 - 强类型 — 每个 query 独立 record(
KLineRow、ProfitRow、RealtimeQuote、EastMoneyKLineRow等) - 自动登录 —
CreateAndLoginAsync()一行搞定 - 可测试 — 协议层与传输层分离,
ITransport可替换
- 多源 Hedged Requests — 500ms hedge 间隔,首个成功胜出,剩余自动取消
- SourceHealthRegistry — 连续 3 次失败自动进入 30s 冷却,不影响其他源
- TCP 自愈 — 半死检测(
socket.Poll+IsConnected属性),断线后自动 reconnect + relogin(CAS 线程安全,最多 1 次重试) - 统一证券代码格式 — 东财风格
SH600519为标准;CodeFormatter向后兼容sh.600519/sh600519/600519.SH/1.600519等格式 - TestUI 子项目 — Web 前端 + minimal API,37 endpoint + 压测面板,用于交易员手动验收 + 开发者冒烟 + 小规模压测
- 财报三表完整查询 —
QueryFullBalanceSheetAsync/QueryFullIncomeStatementAsync/QueryFullCashFlowAsync,东财 P=0 + 新浪 P=1 双源 hedge(500ms),零 BREAKING - 巨潮公告检索 + PDF 下载 —
QueryAnnouncementsAsync按分类(年报 / 半年报 / 季报 / 业绩预告 / 临时公告)检索;DownloadPdfAsync/DownloadPdfToFileAsync支持Range断点续传(206 Partial Content) - TestUI 新端点 —
/api/financial/*(3 个)+/api/cninfo/announcements(POST)+/api/cninfo/pdf-download(GET 流式)
用于交易员手动验收与开发者冒烟测试的内置 Web UI:
dotnet run --project src/Baostock.NET.TestUI浏览器访问 http://localhost:5050,可逐项测试 37 个端点,包含 28 个 baostock TCP 接口、3 个多源 HTTP 接口、6 个内部运维接口,并支持小规模压测。
硬约束:baostock TCP 路径受 concurrency ≤ 1 / duration ≤ 30s / total ≤ 200 硬锁保护(同一 TCP 长连接非线程安全)。
详见 TestUI 使用指南 与 交易员测试手册。
- .NET 9 SDK
- 网络可达
public-api.baostock.com:10030(TCP,用于Query*Async系列) - 网络可达以下 HTTP 数据源(用于 v1.2.0 多源 API
GetRealtimeQuote*Async/GetHistoryKLineAsync):hq.sinajs.cn(Sina 实时)qt.gtimg.cn/web.ifzq.gtimg.cn(Tencent 实时 + K 线)push2.eastmoney.com/push2his.eastmoney.com(EastMoney 实时 + K 线)
dotnet build
dotnet test # 离线单测
dotnet test --filter "Category=Live" # 联网集成测试41 个 TestUI 端点全量实测(基于 commit 2e2afb4):
- HTTP 200 通过:41 / 41
- 业务数据正常:39(PASS)+ 2(空集合规:当日无暂停股 / logout)
- 业务/技术失败:0
- 单元测试:307 passed / 0 failed / 1 skipped
- 编译:0 warning / 0 error
- 响应信封:绝大多数 POST 端点返回
{ok, rowCount, elapsedMs, sources?, data};3 个 GET 元数据端点(session/status、meta/endpoints、loadtest/list-targets)直接返回原始对象/数组,不带信封。 sources字段(v1.3.2+):仅多源对冲端点(multi/*、financial/*、cninfo/*)返回,标记本次胜出的源(Sina/Tencent/EastMoney/Cninfo)。baostock TCP 端点sources=null。- 登录要求:baostock TCP 端点(
/api/baostock/*)必须先调POST /api/session/login登录;多源 HTTP 端点和压测/元数据端点不需要 baostock 登录。 /api/loadtest/run:用durationSeconds(1..300),不是requestCount;baostock TCP 路径硬锁concurrency ≤ 1 / durationSeconds ≤ 30 / total ≤ 200。/api/cninfo/pdf-download:支持 RFC 7233 完整 Range 请求(bytes=A-与bytes=A-B),无效格式(后缀bytes=-N、多段、起始越界)返 416 +Content-Range: bytes */total。evaluation/dividend-data:yearType必填("report"或"operate");evaluation/adjust-factor用dateRange,不用year/quarter。
详见 v1.3.4 端点状态快照:每个端点的请求示例、参数说明、响应字段、性能指标、注意事项。
数据可信度:v1.3.4 已完成 32/32 业务端点 100% 与外部权威源(东方财富 / 巨潮 / 中证指数 / 央行 / 国家统计局 / 上交所 / 深交所)交叉验证,第一轮 16 个 + 第二轮 19 个 = 24 MATCH + 3 内部一致性 + 7 DEVIATION(口径差异已文档化)+ 0 MISMATCH。
- v1.3.4 专集 — 41 端点状态快照 + 开发者协议指南
- v1.3.0 专集 — 财报三表 / 巨潮 PDF / TestUI 新端点 / 从 v1.2.0 迁移
- v1.2.0 专集 — 架构 / 数据源 / 迁移指南 / TestUI 使用
- 入门指南 — 安装、Session、IAsyncEnumerable、错误处理
- CHANGELOG — 各版本变更摘要
- ROADMAP — v1.3.0+ 规划(财报三表、巨潮 PDF、深度数据)
- 交易员测试手册 — 手动验收流程
- API 参考 — DocFX 生成的 API 文档
MIT — see LICENSE.
- baostock — 免费数据服务
- baostock Python 包 — 协议参考实现