Sequoia-X 项目研究站 · 日常运行
Sequoia-X 日常运行:补增量、跑策略、推飞书的一次闭环
装好之后的每个交易日,你只需要执行一次 python main.py。它会先读本地库里已有的股票清单、把当日缺失的日 K 按股票切成最多八份并行补回来,然后依次跑七个形态策略,只有命中的策略才会把结果推到飞书。整个过程由 rich 输出带时间戳的日志,最后用 crontab 固定在收盘后执行。
Sequoia-X 日常模式的五步闭环
步骤与顺序来自 main.py 的日常分支,不是推测。
读本地股票清单
从 SQLite 里
SELECT symbol, MAX(date) FROM stock_daily GROUP BY symbol取出每只股票的最新日期。若库里一只股票都没有,日志会提示「本地无股票数据,请先执行 --backfill」并直接返回——这是首次运行的正常提示。算出需要补哪些股票
只对「最新日期早于今天」的股票生成任务;已经是最新的会被跳过。所有股票都是最新时,日志输出「所有股票已是最新,无需更新」,不做任何网络请求。
八进程并行拉当日增量
任务按
tasks[i::n]切成min(8, 任务数)份,每个子进程自己bs.login()独立拉取,避免单连接串行等待。子进程返回的行在父进程汇总成 DataFrame。清洗后写回 SQLite
数值列转数字、丢掉收盘价为空的记录、过滤
volume <= 0的停牌行;写入前先DELETE FROM stock_daily WHERE date = ?,再按批量 append,保证同一天重复执行不会产生重复行。跑七个策略并按需推送
策略在
main.py的列表里顺序执行,每个策略读同一份本地数据、返回命中的股票代码;命中为空只记日志,命中的才调用飞书推送器并带上该策略的webhook_key。
--backfill),它在安装与回填页里说明。两者不要混着用:日常模式为了补当日缺口会删掉当日记录再写,回填模式则是逐只增量追加。Sequoia-X 的八进程增量做了什么
把并发、去重与容错拆开看,出问题时才知道该查哪一环。
| 环节 | 源码行为 | 适用场景 | 注意点 |
|---|---|---|---|
| 进程数 | n_workers = min(8, len(tasks)) | 全市场日常更新 | 待补股票少于 8 只时进程数自动减少,不会空跑 |
| 任务分片 | chunks = [tasks[i::n_workers] for i in range(n_workers)] | 把清单均匀摊到各进程 | 按步长切分而非按块,各进程负载更均衡 |
| 连接管理 | 每个子进程独立 bs.login() / bs.logout() | 多进程并发取数 | 不共享连接,避免单连接超时影响全部任务 |
| 增量起点 | 从「该股票最新日期 + 1 天」拉到今天 | 按股票精确补缺口 | 库中日期格式需为 YYYY-MM-DD,否则日期解析会失败 |
| 清洗规则 | 丢弃 close 为空、过滤 volume <= 0 | 剔除停牌与脏行 | 停牌日不会进入策略计算,形态窗口按实际交易日滚动 |
| 写入去重 | 先按日期 DELETE 再 append | 同一天重复运行 | 手工重跑当天的日常模式是安全的;但不要用它补历史 |
| 空结果 | 无新行时输出「无新数据(可能非交易日)」并返回 0 | 周末与法定节假日 | 这是预期行为,不要据此判定脚本坏了 |
用 crontab 让 Sequoia-X 收盘后自动运行
官方 README 给出的定时方式是 crontab,示例行如下。
| 片段 | 含义 | 适用场景 | 注意点 |
|---|---|---|---|
15 19 * * 1-5 | 周一到周五 19:15 执行 | A 股收盘(15:00)后数小时 | crontab 不识别节假日,节假日会照跑并输出「无新数据」 |
cd /root/Sequoia-X | 切到项目目录再执行 | 数据库相对路径为 data/sequoia_v2.db | 不切目录会按 cron 的家目录找 data/,等于换了一个空库 |
.venv/bin/python | 用虚拟环境里的解释器 | 依赖装在 venv 里 | 直接写 python 会用到系统解释器,报模块找不到 |
>> log.txt 2>&1 | 标准输出与错误都追加到日志文件 | cron 环境没有终端 | 不加这一段的输出会被丢弃,出问题无从查起 |
| 环境变量 | cron 默认不加载你的 shell 配置 | 项目用 .env + load_dotenv() 读配置 | 把飞书 Webhook 写进项目目录的 .env,不要在 cron 行里硬编码密钥 |
| 改成多时段 | 把 15 19 换成别的时间 | 数据源当日数据更新较晚时 | 当日数据未就绪时拉到空结果属正常,可顺延时间再跑一次 |
cron,做法等价:切到项目目录、用虚拟环境解释器、把输出重定向到日志文件。本项目没有内置调度器,也没有守护进程。Sequoia-X 运行耗时与影响因素
README 的自述数字只作参考,实际耗时随环境变化。
| 运行类型 | 官方自述耗时 | 主要影响因素 | 怎么判断正常 |
|---|---|---|---|
| 日常模式 | 约 2~3 分钟 | 待补股票数量、网络质量、机器 CPU 核数、策略遍历全库的耗时 | 日志里能看到「需要更新 N 只股票」与每条策略的选股数量 |
| 首次回填 | 约 12 分钟 | 单线程逐只拉取、起始日期(默认 2024-01-01)到今天的长度、重试与重连次数 | 每 500 只打印一行「已处理 x/N,成功/跳过/失败」 |
| 跳过的情形 | 数秒 | 全部股票已是最新,或当天不是交易日 | 日志出现「所有股票已是最新」或「无新数据(可能非交易日)」 |
| 策略阶段 | 未单独给出 | 逐只读库 + 向量化计算的规模;定增策略另需请求 akshare | 每个策略结束都有一行「XXXStrategy 选出 N 只股票」 |
| 推送阶段 | 逐策略最多 10 秒超时 | Webhook 响应速度;推送前还要查股票名称 | 成功会记「飞书推送成功 [key],共 N 只股票」 |
| 数据规模 | 约 5200 只 A 股(README 口径) | 股票清单来自 bs.query_stock_basic() 的上市股票过滤 | 回填开始时日志会打印「获取股票列表完成,共 N 只」 |
日志怎么读
日志用 rich 输出,格式固定为「模块名 - 消息」,带方括号时间戳。
| 日志特征 | 含义 | 适用场景 | 注意点 |
|---|---|---|---|
时间戳格式 [%Y-%m-%d %H:%M:%S] | 由 RichHandler 统一渲染 | 排查某天是否真的跑过 | 重定向到文件后不带颜色,属正常 |
| 日志级别是 DEBUG | logger 默认设为 DEBUG | 需要更细的库内输出时 | 日志会比较长,定时任务建议只保留最近若干天 |
WARNING 行带股票代码 | 单只股票计算失败被跳过,不影响其他股票 | 个别标的 K 线不足或数据异常 | 策略内异常被捕获后写 warning,主流程继续 |
| 「无选股结果,跳过推送」 | 该策略当天没有命中标的 | 阈值较严或当日行情不匹配 | 不是错误,也不会发空卡片到飞书 |
| 「主流程发生未捕获异常」+ traceback | 顶层异常处理器打印后以退出码 1 结束 | 配置缺失、数据库不可写等 | cron 不会通知你,建议配合日志检查或另设告警 |
| 同名 logger 只挂一个 handler | 重复调用取 logger 不会重复打印 | 二次开发时自定义模块取日志 | 日志不重复说明幂等逻辑生效,属正常现象 |
日常运行常见问题
每天都必须手动跑一次吗?
不必。官方做法是用 crontab 在工作日收盘后自动执行,示例为 19:15。手动执行等价于把同样一条命令敲一遍,适合调试或补跑当天。具体时间与解释器路径以你的环境和官方 README 为准。
非交易日会报错吗?
不会。没有新数据时日志会输出「无新数据(可能非交易日)」并正常结束,返回写入 0 条。周末与节假日出现这条日志属于预期行为,不要据此判定脚本损坏。
同一天重复运行会写重复数据吗?
日常模式在写入前会按日期先删除当天记录再批量追加,所以手工重跑当天不会产生重复行。但注意表上还有 UNIQUE(symbol, date) 约束,回填路径遇到冲突是把 IntegrityError 静默跳过,两条路径的容错方式不同。
日常模式能补好几天没跑的数据吗?
能补上「每只股票从最新日期到今天」的缺口,但它是按日期整体删除后重写的;如果缺的是较长的历史区间,用回填模式更合适,因为它逐只从断点续拉并跳过已入库股票。选择依据见排障续传页的决策表。
cron 里跑没反应怎么办?
先看有没有重定向日志文件:命令结尾必须有 >> log.txt 2>&1,否则输出直接丢失。其次确认三件事:是否先 cd 到项目目录、是否用虚拟环境里的解释器、.env 里的必填 Webhook 是否已配置。三项都对仍无输出时,看退出码是否为 1。
跑完一次要等多久才算异常?
README 自述日常约 2~3 分钟、回填约 12 分钟,但这是项目自述值,实际取决于机器、网络与待补数量。判断是否卡住的更可靠依据是日志是否还在推进(每 500 只的进度行、每条策略的结果行)。长时间无新日志时按排障页逐项核对。