找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1930

积分

0

好友

252

主题
发表于 前天 22:16 | 查看: 3| 回复: 0

你是否曾羡慕 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 查询能力,两者结合形成了一个零成本、完全本地化的专业研究流水线。

这套方案不仅适用于股票分析,还可以扩展到天气预测、体育数据分析、经济活动研究等任何需要处理大规模数据的场景。你现在拥有的,正是专业机构进行市场分析的技术基础。如果想了解更多关于数据处理和金融科技的实践案例,欢迎来云栈社区交流探讨。




上一篇:掌握Python Lambda函数:9个实战场景与应用技巧解析
下一篇:AI时代中间层全面崩塌:资本、产业与定价策略的杠铃化生存指南
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-12 01:28 , Processed in 0.199312 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表