本地查询股票等历史数据
由bq1fuwkt创建,最终由bq1fuwkt 被浏览 4 用户
问题描述
我想用 BigQuant SDK 查询股票的历史行情数据(如日线、分钟线等),并在本地进行分析处理,应该如何实现?
详细解答
BigQuant SDK 提供了两种主要方式来查询历史数据:
方法一:使用 DAI SQL 查询(推荐)
适用于需要灵活查询、过滤、聚合数据的场景。
- 基础查询 - 查询单只股票的日线数据
例如 我们要查询平安银行 2024 年 1 月份的日线数据
import bigquant
result = bigquant.dai.query("""
SELECT date, instrument, open, high, low, close, volume
FROM cn_stock_bar1d
WHERE instrument = '000001.SZ'
AND date >= '2024-01-01'
AND date <= '2024-01-31'
ORDER BY date
""")
# 转换为 Pandas DataFrame
df = result.df()
print(df.head())
- 关键说明
- cn_stock_bar1d 是 A 股日线数据表,包含开高低收成交量等字段
- 支持标准 SQL 语法进行过滤、排序、聚合等操作
- 查询结果
\
- 批量查询 - 查询多只股票数据
例如 查询 平安银行、万科A、浦发银行 三只股票 2024 年的数据
import bigquant
result = bigquant.dai.query("""
SELECT date, instrument, close, volume
FROM cn_stock_bar1d
WHERE instrument IN ('000001.SZ', '000002.SZ', '600000.SH')
AND date >= '2024-01-01'
AND date <= '2024-12-31'
ORDER BY date, instrument
""")
print(result.df())
- 查询结果
\
- 使用过滤器优化查询性能
例如 我们要查询 平安银行、万科A 在 "2024-01-01", "2024-01-02", "2024-01-03" 三天的数据
import bigquant
result = bigquant.dai.query(sql="""
SELECT date, instrument, open, high, low, close, volume
FROM cn_stock_bar1d
WHERE instrument IN ('000001.SZ', '000002.SZ')
ORDER BY date
""",
filters={
"date": ["2024-01-01", "2024-01-02", "2024-01-03"] # 只查询这3天的数据
}
)
print(result.df())
- 关键说明
- filters 参数会在底层数据存储层面过滤,性能优于 SQL WHERE 条件
- 适用于按日期、按分区列进行精确过滤的场景
- 查询结果
\
- 参数化查询 - 动态传入查询条件
例如 我们查询 平安银行、浦发银行 2024 年的数据
import bigquant
instruments = ['000001.SZ', '600000.SH']
start_date = '2024-01-01'
end_date = '2024-12-31'
result = bigquant.dai.query(sql="""
SELECT date, instrument, close, volume
FROM cn_stock_bar1d
WHERE instrument IN $instruments
AND date >= $start_date
AND date <= $end_date
ORDER BY date
""",
params={
"instruments": instruments,
"start_date": start_date,
"end_date": end_date
}
)
print(result.df())
- 查询结果
\
- 绑定本地数据进行查询
例如 我们本地有一个股票列表
import pandas as pd
import bigquant
local_stocks = pd.DataFrame({
'instrument': ['000001.SZ', '000002.SZ', '600000.SH'],
'weight': [0.4, 0.3, 0.3]
})
现在,我们要将本地数据绑定到 SQL 查询中进行查询
result = bigquant.dai.query(sql="""
SELECT a.date, a.instrument, a.close, b.weight
FROM cn_stock_bar1d AS a
JOIN my_stocks AS b ON a.instrument = b.instrument
WHERE a.date >= '2024-01-01' AND a.date <= '2024-12-31'
ORDER BY a.date
""",
bind_relations={
"my_stocks": local_stocks # 将本地 DataFrame 作为临时表
}
)
print(result.df())
- 关键说明
- bind_relations 会自动将本地 DataFrame 上传为临时 DataSource
- 上传的数据在查询中可作为普通表使用
- 适用于需要结合本地数据进行联合查询的场景
- 查询结果
方法二:使用 DataSource 直接读取
适用于需要完整读取某个数据源的场景(无需复杂查询)。
\
- 创建 DataSource 对象
例如 我们获取 日线数据表 cn_stock_bar1d
import bigquant
ds = bigquant.dai.DataSource("cn_stock_bar1d")
\
- 读取数据(可指定分区过滤)
例如 针对上方获取的 DataSource,我们选取"2024-01-01", "2024-01-02"两天的数据,同时限定 "date", "instrument", "close", "volume"这些字段
table = ds.read_bdb(
partition_filter={"date": ["2024-01-01", "2024-01-02"]}, # 只读取这2天的数据
columns=["date", "instrument", "close", "volume"] # 只读取这些列
)
将结果转换为 DataFrame
df = table.to_pandas()
print(df.head())
- 关键说明
- read_bdb() 默认返回 PyArrow Table(性能最优)
- 可通过 as_type=pd.DataFrame 直接返回 DataFrame
- partition_filter 和 columns 参数可减少数据传输量,提高速度
- 多种数据格式支持
- 查询结果
获取查询结果的不同格式
接下来我们来查看如何获取不同格式的 dai.query 查询结果,首先获取查询结果:
result = bigquant.dai.query("SELECT * FROM cn_stock_bar1d LIMIT 5")
\
- Pandas DataFrame(最常用)
df = result.df()
print(df)
- 转换结果
\
- PyArrow Table(性能最优,适合大数据)
table = result.arrow()
print(table)
- 转换结果
\
- Polars DataFrame(高性能替代品)
pl_df = result.pl()
print(pl_df)
- 转换结果
关键概念解释
DAI (Data Access Interface)
BigQuant 的数据访问接口,支持使用 SQL 查询海量金融数据。查询在云端执行,结果通过 Arrow Flight 高速传输到本地。
DataSource
数据源对象,代表 BigQuant 平台上的一个数据表。可直接读取完整数据源,或作为 SQL 查询的表名使用。
QueryResult
查询结果对象,提供多种格式转换方法:
- .df(): 转为 Pandas DataFrame
- .arrow(): 转为 PyArrow Table(零拷贝,性能最优)
- .pl(): 转为 Polars DataFrame
常用数据表
- cn_stock_bar1d: A 股日线数据
- cn_stock_bar1m: A 股分钟线数据
- cn_stock_prefactors: A 股复权因子
- cn_stock_tick: A 股 Tick 数据
filters vs WHERE
- filters 参数:在存储层面过滤(性能更好,推荐用于日期、分区列)
- WHERE 子句:在计算层面过滤(更灵活,支持复杂条件)
bind_relations
将本地 DataFrame 上传为临时数据源,可在 SQL 中作为表使用。适用于:
- 本地持仓数据与历史行情联合查询
- 自定义股票池与基础数据关联
- 本地计算结果与云端数据融合
性能优化建议
- 使用 filters 参数:对日期等分区字段使用 filters,而非 WHERE,可大幅提升查询速度
- 只查询需要的列:使用 SELECT 指定列名,避免 SELECT *
- 优先使用 PyArrow Table:如果后续处理可使用 Arrow,避免转换为 Pandas
注意事项
- 全表扫描限制:默认不允许全表扫描,需要设置 full_db_scan=True
- 临时数据源:bind_relations 上传的数据为临时数据源,查询结束后自动清理
更多资料
\