免费数据源,无需注册
README 说明数据层使用 baostock 拉取历史与增量日 K,并称其免费、无需注册、不限流。项目不需要你申请 API Key,也不产生数据费用;代价是数据频率只有日线,且依赖该服务的可用性。
Sequoia-X 项目研究站 · 数据层
整套选股系统的地基是一张本地表:stock_daily。数据来自 baostock 的日 K(按后复权口径拉取),日常模式用多进程把当日增量补进来,首次用回填模式把历史一次性灌满。数据库就是一个文件,路径由 DB_PATH 控制,默认落在项目的 data/sequoia_v2.db,可以直接拷贝到另一台机器继续用。
这三个选择决定了它与其他取数方式的不同。
README 说明数据层使用 baostock 拉取历史与增量日 K,并称其免费、无需注册、不限流。项目不需要你申请 API Key,也不产生数据费用;代价是数据频率只有日线,且依赖该服务的可用性。
拉取时使用 adjustflag="1"(后复权)。README 的解释是后复权保持历史价格不变,因此增量写入不会因为后续除权导致既有数据错乱——这是「本地增量存库」这条路能成立的前提。
数据落在单个 SQLite 文件里,意味着同一天的形态判断在本地是确定的、可重复的,也能整库搬迁或备份。README 用「彻底规避东方财富反爬」来描述动机,这属于项目自述的表述,不是技术保证。
建表语句在 data/engine.py 里,字段与 baostock 返回列一一对应。
| 字段 | 类型与约束 | 来源 / 含义 | 注意点 |
|---|---|---|---|
id | INTEGER PRIMARY KEY AUTOINCREMENT | SQLite 自增主键 | 仅用于行标识,策略不使用该列 |
symbol | TEXT NOT NULL | 纯数字股票代码(如 600519、000001) | 入库前会从 baostock 的 sh.600000 形式里去掉市场前缀 |
date | TEXT NOT NULL | 交易日,文本格式 | 日常模式按「最新日期 + 1 天」推算增量起点,格式必须是可解析的日期字符串 |
open / high / low / close | REAL | 后复权的开高低收 | 后复权价与行情软件显示的真实成交价不同,不要直接与看盘软件比数字 |
volume | REAL | 成交量 | 落库前过滤 volume <= 0,停牌与异常行不会进入策略计算 |
turnover | REAL | 成交额;回填路径由 baostock 的 amount 改名而来 | 海龟策略的「成交额过亿」判断用的就是这一列 |
| 约束与索引 | UNIQUE(symbol, date) + 索引 idx_symbol_date(symbol, date) | 保证同股同日不重复,加速按股票查询 | 两条写入路径都依赖它:日常先删后写、回填把冲突静默跳过 |
| 建表方式 | CREATE TABLE IF NOT EXISTS + CREATE INDEX IF NOT EXISTS | 每次启动引擎时执行 | 首次运行会自动创建目录与库文件,不需要手工建表 |
同一个库被两种方式写入,容错策略完全不同。
| 对比项 | 日常增量 sync_today_bulk | 历史回填 backfill | 适用场景 |
|---|---|---|---|
| 并发 | 多进程(最多 8) | 单线程顺序拉取 | 日常求快、回填求稳 |
| 起点 | 每只股票「最新日期 + 1 天」到今天 | 库内为空的用 START_DATE,已有的从断点续拉 | 首次建库用回填,之后用日常 |
| 写入前动作 | 对涉及的每个日期先 DELETE FROM stock_daily WHERE date = ? | 无删除,直接追加 | 日常可安全重跑同一天 |
| 列名映射 | 拉取时直接请求 amount 并命名为 turnover | 先取 amount 再 rename 成 turnover | 两条路最终落到同一列 |
| 冲突处理 | 先删后写,一般不触发约束冲突 | 捕获 sqlite3.IntegrityError 后静默跳过 | 回填重跑不会因重复行中断 |
| 失败重试 | 子进程内单只失败即跳过(记录在返回结果里) | 单只重试 3 次(2s / 4s / 8s),每次重试前重连 | 回填更适合应对长连接超时 |
| 进度可见性 | 汇总后打印写入条数 | 每 500 只打印成功 / 跳过 / 失败计数,结束再汇总 | 回填耗时长,需要进度反馈 |
| 重连策略 | 每个子进程各自 login / logout | 每处理 200 只强制 logout 后重新 login | 规避单连接长时间存活被断开 |
清单来自 baostock 的基础信息接口;展示与链接时会再转一次格式。
| 环节 | 规则 | 适用场景 | 注意点 |
|---|---|---|---|
| 取全市场清单 | bs.query_stock_basic(code_name="", code="") | 回填前确定标的范围 | 接口一次性返回基础信息,需要自己按字段过滤 |
| 过滤条件 | 仅保留 status == "1"(上市)且 stock_type == "1"(股票) | 排除退市与指数等非股票品种 | 这也是「约 5200 只」这个口径的由来 |
| 入库代码 | 取 "sh.600000".split(".")[1] 的纯数字部分 | 库内统一为 6 位数字 | 策略与推送都基于纯数字代码,不带市场前缀 |
| 取数时代码 | 6 / 9 开头 → sh.,其余 → sz. | 把库内代码转回 baostock 格式 | 北交所标的的代码段不在这条规则的显式分支里,实际以你能拉到的数据为准 |
| 推送链接代码 | 6 开头 → SH,4 / 8 开头 → BJ,其余 → SZ | 生成雪球链接(xueqiu.com/S/<code>) | 两套前缀规则不同,读源码时注意区分 |
| 股票名称 | 推送前用 bs.query_stock_basic(code=...) 逐只查名称 | 卡片上显示中文名 | 查不到名称时回退用代码本身,不会中断推送 |
单文件存储带来的便利与要留意的地方。
| 项目 | 说明 | 适用场景 | 注意点 |
|---|---|---|---|
| 默认路径 | data/sequoia_v2.db(相对项目根目录) | 本地开发与定时任务 | 相对路径意味着必须在项目目录下执行,cron 里要显式 cd |
| 改路径 | 改 .env 的 DB_PATH | 想放到数据盘或共享目录 | 父目录会被自动创建,不需要手工建文件夹 |
| 起始日期 | START_DATE 默认 2024-01-01 | 决定回填的历史深度 | 它只影响「库里还没有的股票」的起点;要改历史深度需要清库重填 |
| 备份 | 直接复制该文件(建议在程序未运行时进行) | 迁移到新机器或留档 | 写入过程中复制可能拿到不一致的快照 |
| 体积 | 未给出官方数字;随标的数与历史长度增长 | 容量规划 | 第三方页面给出的「2GB 磁盘」等数字非官方口径,本站不采用 |
| 并发写 | 多进程只并行「拉取」,写库在父进程串行完成 | 避免 SQLite 写锁竞争 | 不要在任务运行时另开进程写同一文件 |
先确认口径,再决定要不要用它做研究。
| 维度 | 实际情况 | 适用场景 | 注意点 |
|---|---|---|---|
| 频率 | 只有日线(frequency="d") | 日频形态扫描 | 没有分钟线与分时数据,日内策略不适用 |
| 复权方式 | 后复权(回填与增量一致) | 跨除权日的区间比较 | 价格数值不等于真实成交价,展示时不要与行情软件混用 |
| 基本面 | 没有任何财务字段 | 纯技术面研究 | 估值、业绩类筛选需要另找数据源 |
| 品种覆盖 | 按基础信息过滤后的 A 股股票 | 个股形态扫描 | 不含 ETF / 基金 / 指数成分(指数只用于对照) |
| 停牌处理 | 过滤 volume <= 0 的行 | 避免停牌日污染形态窗口 | 窗口按实际入库的交易日滚动,与自然日不等长 |
| 数据质量 | 依赖上游数据源;项目未做完整性校验 | 研究用途可接受 | 本站不宣称数据「完全没有缺失」,重要决策前请自行交叉核对 |
源码里拉取参数是 adjustflag="1"(后复权)。README 给出的理由是后复权下历史价格不变,增量写入时旧的记录不需要重算,适合这套「每天只补增量」的存储方式。口径细节以官方 README 与 baostock 文档为准。
因为库里存的是后复权价,行情软件默认多显示不复权价。两者在除权除息后会分叉,这是设计使然而不是数据错误。要做展示或对比时,请注明复权口径。
表结构是公开的,理论上可以手工插入或另写脚本导入,但要注意两点:UNIQUE(symbol, date) 约束会拒绝重复行;以及策略假定 date 是可排序解析的日期字符串。自行写入导致的结果差异由你自己承担,本站不做保证。
写库动作都在单个进程里串行执行,并发只用在「拉取」阶段;日常模式按日期先删后写,回填模式靠 UNIQUE 约束把重复行静默跳过。因此不要在同一时间同时跑两个模式,正常使用下二者是互补的。
高窄旗形与上升趋势跌停这两个策略会直接跳过 K 线不足的标的。解决办法是把 START_DATE 往前提(例如更早的年份)并重跑回填;默认值是 2024-01-01,历史深度越深,能参与计算的标的越多,但回填耗时也越长。
可以。它是单个 SQLite 文件,迁移后把 DB_PATH 指向新位置即可继续日常更新。注意目录相对路径的基准是「执行命令时所在的目录」,在定时任务里要显式切到项目目录。