【量化系统从零构建 #04】存储设计:选型·建库·交易日历

【量化系统从零构建 #04】存储设计:选型·建库·交易日历

系列:《量化系统从零构建》|连载项目 · 纯 GET 取数 · 仅依赖 requests

适用:想给取数层配一个本地存储底座的读者;本篇是纯本地存储层,不发起网络请求,直接基于标准库 sqlite3 建库,为 #05 行情落库铺路。

1. 你将得到什么

  • 存储选型结论 :落库用 SQLite (零依赖、单文件、随开随用);分析导出用 Parquet (列式、压得小);即席分析用 DuckDB(直接 SQL 读 Parquet)。新手默认 SQLite 就够。
  • 建库函数 init_db :建好 trade_calendar(交易日历)与 stocks(股票清单)两张骨架表。
  • 交易日历 seed_calendar:用标准库生成工作日(周一至周五)写入日历表,并给出「取某月首个交易日」示例。
  • 本篇交付 :后续 #05--#08 的所有落库表都挂在这个库上,取数层(ZhituClient)拉到的数据落进这里。

2. 本篇取数约定

本篇是纯本地存储层,不发起任何网络请求 ,直接用 Python 标准库 sqlite3,不装任何第三方数据库驱动。下面的代码可在本地直接跑。

3. 存储选型对比

方案 角色 优点 何时用
SQLite 主落库 单文件、零依赖、事务稳 默认;每日增量更新、按代码/日期查询
Parquet 分析导出 列式压缩、读大表快 把日线/财务导出给 pandas 做离线分析
DuckDB 即席分析 直接 SQL 读 Parquet,免加载 多文件聚合、复杂 SQL 透视

本系列默认 SQLite 落库。Parquet / DuckDB 是「分析延伸」,用到时再引入,不影响主线。

4. 核心模板函数

python 复制代码
import sys, sqlite3, datetime

# ── 建库:交易日历 + 股票清单骨架 ──
def init_db(path=":memory:"):
    """建库并返回连接。path 给文件名即落盘,给 :memory: 即内存库。"""
    conn = sqlite3.connect(path)
    cur = conn.cursor()
    cur.execute("""
    CREATE TABLE IF NOT EXISTS trade_calendar (
        date TEXT PRIMARY KEY,
        year INT, month INT, day INT, weekday INT,
        is_trading_day INT
    )""")
    cur.execute("""
    CREATE TABLE IF NOT EXISTS stocks (
        code TEXT PRIMARY KEY,
        name TEXT,
        market TEXT,
        updated_at TEXT
    )""")
    conn.commit()
    return conn


def _weekdays(start, end):
    """生成 [start, end] 内的周一至周五(近似交易日,未剔除法定节假日)。"""
    s = datetime.date.fromisoformat(start)
    e = datetime.date.fromisoformat(end)
    d, out = s, []
    while d <= e:
        if d.weekday() < 5:            # 0=周一 ... 4=周五
            out.append(d)
        d += datetime.timedelta(days=1)
    return out


def seed_calendar(conn, start, end):
    """把 [start, end] 的工作日写入交易日历表,返回写入条数。"""
    cur = conn.cursor()
    rows = [(d.isoformat(), d.year, d.month, d.day, d.weekday(), 1)
            for d in _weekdays(start, end)]
    cur.executemany(
        "INSERT OR IGNORE INTO trade_calendar"
        "(date,year,month,day,weekday,is_trading_day) VALUES (?,?,?,?,?,?)", rows)
    conn.commit()
    return len(rows)


def first_trading_day(conn, year, month):
    """返回某年某月的第一个交易日(ISO 字符串),无则 None。"""
    cur = conn.cursor()
    cur.execute(
        "SELECT date FROM trade_calendar WHERE year=? AND month=? ORDER BY date LIMIT 1",
        (year, month))
    row = cur.fetchone()
    return row[0] if row else None


def run_check():
    # 合成数据仅逻辑校验(标准库,非真实行情)
    conn = init_db(":memory:")
    n = seed_calendar(conn, "2024-01-01", "2024-01-31")
    assert n == 23, n                      # 2024-01 共 23 个工作日
    cur = conn.cursor()
    cur.execute("SELECT COUNT(*) FROM trade_calendar WHERE weekday>=5")
    assert cur.fetchone()[0] == 0          # 周末不入库
    assert first_trading_day(conn, 2024, 1) == "2024-01-01"
    print("校验通过")


if __name__ == "__main__":
    if len(sys.argv) > 1 and sys.argv[1] == "--check":
        run_check()
    else:
        conn = init_db("quant.db")
        print("交易日历已建,2024-01 工作日数:",
              seed_calendar(conn, "2024-01-01", "2024-01-31"))

5. 跑通示例

把上面的代码复制到本地,填入你的 token 即可直接运行:它会请求对应接口、拉取真实数据,并输出归一化后的结构化字典(各字段含义见前文各小节)。

6. 坑与注意事项

  1. 近似交易日历要补节假日 :_weekdays 只排除周末,未剔除法定节假日(如元旦、春节)。实盘前需补一份交易日集合(可先用历史数据反推或手动维护一张表)。
  2. INSERT OR IGNORE 防重 :日历 date 是主键,重跑 seed_calendar 不会重复插入。
  3. 内存库 :memory: 仅当次会话有效 :run_check 用内存库验证逻辑;正式落库请传真实文件名(如 quant.db)。
  4. SQLite 并发写入弱:本系列是单进程定时更新,够用;多进程并发写要上 WAL 或换引擎。

7. 小结与下篇预告

本篇把存储底座钉死:SQLite 主库 + 交易日历表,并给出选型对比(Parquet / DuckDB 作分析延伸)。这是 #05--#08 落库章节的共同地基。

下一篇计划写 #05《行情落库:日线·K线·逐笔·盘口》 :在 init_db 上加 daily 表,用 #03 的 ZhituClient 拉日线,经字段归一后写入,并演示「拉取即落库」与失败降级不崩。

8. 免责声明

本文仅演示本地存储与接口字段归一的用法,所有代码示例均为演示数据,未含任何真实数据;文中示例数据仅作演示用途,不构成投资建议,亦不承诺收益。

相关推荐
YOLO数据集集合3 小时前
无人机桥梁损伤目标检测数据集 | 桥梁损伤 无人机巡检 结构健康监测 多类别检测9135期
人工智能·目标检测·无人机
动恰客流统计3 小时前
景区客流统计怎么做?兼顾管控与运营的实施方案解析
大数据·前端·人工智能
weixin_443883013 小时前
合规整改倒计时:高等级签名证书的应用场景
大数据·人工智能·法大大·法大大电子签·电子合同
魔猴疯猿3 小时前
从0到1用Python开发第一个智能体
人工智能·python·深度学习·神经网络·机器学习
wuminyu4 小时前
C++协程实现接收端的零拷贝Buffer管理原理剖析
java·linux·c语言·jvm·c++
天一生水water4 小时前
变分模态分解(VMD)的教程
人工智能
荆棘鸟智能4 小时前
林业遥感长势评估怎么做?从NDVI时序分析到LiDAR蓄积量回归
人工智能·算法·智慧林业
代码方舟4 小时前
数据科学风控实战:基于天远全能消金报告构建自动化信用评估网关
运维·人工智能·自动化
Yan-英杰4 小时前
2026年数据采集服务怎么选?4大主流平台(亮数据 Bright Data、Apify、ScrapingBee、Zyte)深度对比
人工智能·神经网络·microsoft·机器学习·ai开发工具