你是否曾羡慕 Jane Street、Goldman Sachs 等顶级对冲基金的数据分析能力?他们拥有专业团队管理的研究数据库,能够存储海量股票价格、结合经济指标、进行大规模高级分析。
好消息是,借助 Python 生态中的两个强大工具 Polars 和 DuckDB,你可以在自己的笔记本电脑上,用不到 10 分钟的时间,搭建一个快速、免费、完全本地化的研究数据库,轻松处理百万级别的股票数据。
本文将带你从零开始,使用 Yahoo Finance 的真实股票数据,构建一个专业级的本地研究数据库。
为什么要搭建本地数据库?
AWS、Google BigQuery、Snowflake 等云服务固然强大,但它们带来持续的成本和复杂的配置。对于独立研究者、学生或小型基金来说,这些成本往往是不必要的。
本地研究数据库的优势在于:零成本运行,完全在本地执行;极致速度,Polars 和 DuckDB 能在数秒内处理百万行数据;数据隐私,你的研究数据永远不会离开你的电脑;高度灵活,可以自由组合股票数据、经济指标和其他数据源。
技术选型:为什么是 Polars 和 DuckDB?
Polars 是一个用 Rust 编写的高性能 DataFrame 库。相比传统的 Pandas,它在处理百万行以上的数据时,过滤和分组操作通常快 2 到 5 倍。它能自动利用多核 CPU,内存占用更低,语法也非常简洁。
DuckDB 则是一个快速的分析型数据库引擎,专为 OLAP(联机分析处理)场景优化。它无需独立服务器,直接在你的 Python 进程中运行,能够高效处理数千万行数据,并与 Polars、Pandas、Parquet 文件无缝集成。
环境准备
首先安装必要的 Python 库:
pip install polars yfinance duckdb pyarrow matplotlib
确保你的 Python 版本在 3.8 以上:
python --version
第一步:获取股票数据
创建一个新的脚本文件,导入所需的库并获取 NVIDIA(NVDA)的股票数据:
import polars as pl
import yfinance as yf
import duckdb
import matplotlib.pyplot as plt
# 从 Yahoo Finance 下载 NVDA 2024 年全年的股票数据
try:
prices = yf.download("NVDA", start="2024-01-01", end="2025-01-01")
except Exception as e:
print(f"下载数据时出错:{e}")
exit()
# 将 Pandas DataFrame 转换为 Polars DataFrame,并添加股票代码列
df = pl.from_pandas(prices.reset_index()).with_columns(
pl.lit("NVDA").alias("symbol") # 为每一行添加股票代码标识
)
print(df.head()) # 查看前几行数据
第二步:创建 DuckDB 数据库
连接 DuckDB 并将数据存入数据库:
# 连接到本地数据库文件,如果不存在会自动创建
con = duckdb.connect("stocks.db")
# 将 Polars DataFrame 直接加载为数据库表
con.execute("""
CREATE TABLE IF NOT EXISTS stocks AS SELECT * FROM df
""")
# 验证数据是否成功导入
row_count = con.execute("SELECT COUNT(*) FROM stocks").fetchone()
print(f"表中的数据行数:{row_count[0]}") # 一年约 250 个交易日
第三步:使用 SQL 进行数据分析
数据入库后,你就可以使用强大的 SQL 语句进行各种分析了。
计算平均收盘价:
# 按股票代码分组,计算平均收盘价
avg_close = con.execute("""
SELECT symbol, ROUND(AVG("('Close', 'NVDA')"), 2) AS avg_close
FROM stocks
GROUP BY symbol
""").fetchdf()
print(avg_close)
查找成交量最高的 5 个交易日:
# 找出成交量最大的 5 天,通常对应重大新闻或财报发布
high_vol = con.execute("""
SELECT symbol, "('Date', '')", "('Volume', 'NVDA')", "('Close', 'NVDA')"
FROM stocks
ORDER BY "('Volume', 'NVDA')" DESC
LIMIT 5
""").fetchdf()
print(high_vol)
计算 20 日滚动成交量加权平均价格(VWAP):
# VWAP 是交易员常用的执行基准指标
vwap_query = """
WITH daily_vwap AS (
SELECT
"('Date', '')",
symbol,
SUM("('Volume', 'NVDA')" * "('Close', 'NVDA')") / SUM("('Volume', 'NVDA')") AS vwap
FROM stocks
GROUP BY "('Date', '')", symbol
),
rolling_vwap AS (
SELECT
"('Date', '')",
symbol,
AVG(vwap) OVER (
PARTITION BY symbol
ORDER BY "('Date', '')"
ROWS BETWEEN 19 PRECEDING AND CURRENT ROW
) AS rolling_20d_vwap
FROM daily_vwap
)
SELECT * FROM rolling_vwap
ORDER BY symbol, "('Date', '')";
# 执行查询并转换为 Polars DataFrame
vwap_df = pl.DataFrame(con.execute(vwap_query).fetchdf())
vwap_df = vwap_df.rename({"'Date', '')": "Date"})
# 绘制 20 日滚动 VWAP 趋势图
vwap_df.to_pandas().plot(x="Date", y="rolling_20d_vwap", title="20 日滚动 VWAP")
plt.show()
第四步:扩展数据库
单只股票的数据库功能有限,真正的研究数据库需要包含多只股票:
# 批量添加多只股票的数据
symbols = ["NVDA", "AAPL", "TSLA"]
for sym in symbols:
# 下载每只股票的历史数据
prices = yf.download(sym, start="2024-01-01", end="2025-01-01")
# 转换为 Polars DataFrame 并添加股票代码
df = pl.from_pandas(prices.reset_index()).with_columns(
pl.lit(sym).alias("symbol")
)
# 插入到数据库表中
con.execute("INSERT INTO stocks SELECT * FROM df")
# 跨股票对比分析:计算各股票的平均收盘价
comparison = con.execute("""
SELECT symbol, ROUND(AVG(Close), 2) AS avg_close
FROM stocks
GROUP BY symbol
""").fetchdf()
print(comparison)
第五步:计算收益率和突破信号
使用 Polars 计算日收益率:
# 计算每日收益率:今日收盘价 / 昨日收盘价 - 1
df = df.with_columns(
(pl.col("Close") / pl.col("Close").shift(1) - 1).alias("daily_return")
)
使用 SQL 窗口函数检测价格突破(收盘价高于 50 日均线):
# 检测多头突破信号:当收盘价突破 50 日均线时
breakout_query = """
WITH ma AS (
SELECT
Date,
symbol,
Close,
AVG(Close) OVER (
PARTITION BY symbol
ORDER BY Date
ROWS BETWEEN 49 PRECEDING AND CURRENT ROW
) AS ma_50
FROM stocks
)
SELECT *
FROM ma
WHERE Close > ma_50;
breakouts = con.execute(breakout_query).fetchdf()
print(breakouts)
进阶扩展方向
这个基础系统可以继续扩展:添加更多股票,覆盖指数、行业板块或 ETF;整合经济数据,通过 FRED API 导入 GDP、CPI、失业率等宏观指标;结合另类数据,如新闻情绪、Google 趋势或加密货币价格;导出分析结果,保存为 Parquet 或 CSV 格式便于分享;构建可视化仪表板,使用 Streamlit 或 Dash 创建交互式研究工具。
DuckDB 还能直接查询 Parquet 文件而无需导入表中,非常适合处理超大规模数据集。
总结
通过本文,你学会了如何在 10 分钟内搭建一个专业级的本地研究数据库。Polars 负责高效的数据处理和转换,DuckDB 提供强大的 SQL 查询能力,两者结合形成了一个零成本、完全本地化的专业研究流水线。
这套方案不仅适用于股票分析,还可以扩展到天气预测、体育数据分析、经济活动研究等任何需要处理大规模数据的场景。你现在拥有的,正是专业机构进行市场分析的技术基础。如果想了解更多关于数据处理和金融科技的实践案例,欢迎来云栈社区交流探讨。