第 9 章 · 03 扩展方向与架构反思 本节摘要:本节是全教程的「收官反思」——讨论 Sequoia-X 的「下一步」与「局限性」。Sequoia-X 是一套设计良好但有意克制的系统——不试图做所有事。但它的「分层架构 + 抽象基类 + 列表注册」让「扩展」特别容易。本节会从三个维度讨论扩展方向:①加新策略(最简单,2 行代码)、②加新数据源(中等,封装为 BaseStrategy)、③加新触达渠道(较简单,复用卡片结构)。然后讨论 Sequoia-X 的「明确不做」的事——自动交易、实时行情、回测系统——这些是工程边界的克制。最后给出一份「复刻 Sequoia-X 风格的实践指南」——让你把这套思想用到自己的项目里。 内容来源:原项目架构分析 + 通用软件工程实践。
本节摘要:本节是全教程的「收官反思」——讨论 Sequoia-X 的「下一步」与「局限性」。Sequoia-X 是一套设计良好但有意克制的系统——不试图做所有事。但它的「分层架构 + 抽象基类 + 列表注册」让「扩展」特别容易。本节会从三个维度讨论扩展方向:①加新策略(最简单,2 行代码)、②加新数据源(中等,封装为 BaseStrategy)、③加新触达渠道(较简单,复用卡片结构)。然后讨论 Sequoia-X 的「明确不做」的事——自动交易、实时行情、回测系统——这些是工程边界的克制。最后给出一份「复刻 Sequoia-X 风格的实践指南」——让你把这套思想用到自己的项目里。
内容来源:原项目架构分析 + 通用软件工程实践。
💡 核心心法:好的「可扩展架构」不是「支持一切」,而是「支持新场景时改动最小」——Sequoia-X 的「抽象基类 + 列表注册」正是为此设计。
阅读完本章,你应当能够:
Sequoia-X 的最简单扩展——加新策略:
# 1. 写一个新策略类 class MacdStrategy(BaseStrategy): """MACD 金叉策略(教学示例)""" webhook_key = "macd" _MIN_BARS = 35 def run(self) -> list[str]: symbols = self.engine.get_local_symbols() selected = [] for symbol in symbols: try: df = self.engine.get_ohlcv(symbol) if len(df) < self._MIN_BARS: continue # MACD 计算 ema12 = df["close"].ewm(span=12, adjust=False).mean() ema26 = df["close"].ewm(span=26, adjust=False).mean() df["dif"] = ema12 - ema26 df["dea"] = df["dif"].ewm(span=9, adjust=False).mean() last = df.iloc[-1] prev = df.iloc[-2] if prev["dif"] < prev["dea"] and last["dif"] > last["dea"]: selected.append(symbol) except Exception: continue return selected # 2. 在主程序入口的列表里追加一行 strategies = [ MaVolumeStrategy(engine, settings), # ... 已有 7 个 ... MacdStrategy(engine, settings), # ← 新增 ]
总工程成本:
| 修改位置 | 改动量 | 风险 |
|---|---|---|
| 写新策略类 | ~30 行 | 独立文件,不影响其他 |
| 列表里追加 | 1 行 | 极低 |
| 可选:加专属 Webhook | 0~1 行 配置 | 极低 |
| 总成本 | 30~50 行 + 1 行 | 零破坏性 |
加新策略的工程成本远低于「理解业务」——这正是「模板方法模式」的价值。
如果想接入「非 baostock 行情」或「非 akshare 事件」数据源——比如「通达信」「Tushare Pro」「自己爬的数据」——需要封装一个新的数据源模块。
设计原则:
class NewDataSource: """新数据源(教学示例:通达信)。""" def __init__(self, settings: Settings): self.settings = settings def login(self) -> None: """登录/认证。""" ... def fetch_history(self, symbol: str, start: str, end: str) -> pd.DataFrame: """拉取历史 K 线。返回与 Sequoia-X 行情格式一致的 DataFrame。""" ... def fetch_today(self) -> pd.DataFrame: """拉取今日 K 线(增量同步用)。""" ... def logout(self) -> None: """登出/清理。""" ...
关键约束:
symbol/date/open/high/low/close/volume/turnover);工程成本:
| 工作 | 改动量 |
|---|---|
| 写新数据源类 | 150300 行 |
替换 engine 内部调用 |
~50 行(要保持接口兼容) |
| 测试新数据源 | ~100 行(属性测试) |
| 总成本 | 300500 行 |
加新数据源比加新策略重 5~10 倍——但仍在合理范围。
如果想用「企业微信」「Slack」「Discord」替代「飞书」——复用卡片结构就能快速接入。
设计原则:
# 抽象基类 class BaseNotifier(ABC): @abstractmethod def send(self, symbols: list[str], strategy_name: str, webhook_key: str) -> None: ... # 飞书实现(已有) class FeishuNotifier(BaseNotifier): def send(self, ...): # 飞书交互卡片 ... # 企业微信实现(新) class WeComNotifier(BaseNotifier): def send(self, ...): # 企业微信 markdown 消息 ... # Slack 实现(新) class SlackNotifier(BaseNotifier): def send(self, ...): # Slack block kit ...
主程序入口的修改:
# 之前:notifier = FeishuNotifier(settings) # 之后:根据配置选 notifier notifier_type = settings.notifier_type # "feishu" | "wecom" | "slack" if notifier_type == "feishu": notifier = FeishuNotifier(settings) elif notifier_type == "wecom": notifier = WeComNotifier(settings) # ...
工程成本:
| 工作 | 改动量 |
|---|---|
| 写新 notifier | 100200 行 |
| 主程序入口的工厂方法 | ~20 行 |
| 测试 | ~50 行 |
| 总成本 | 200300 行 |
加新触达渠道比加新数据源轻——因为触达层接口简单。
把三种扩展的成本画成金字塔:
┌──────────────┐ │ 加新触达渠道 │ ← 200~300 行,半天 └──────────────┘ ▲ │ ┌──────────────┐ │ 加新数据源 │ ← 300~500 行,1~2 天 └──────────────┘ ▲ │ ┌──────────────┐ │ 加新策略 │ ← 30~50 行,1 小时 └──────────────┘
加新策略最便宜、加新触达渠道其次、加新数据源最贵——这与各层的接口复杂度成正比。
好的系统不试图做所有事——Sequoia-X 也有明确不做的边界:
| 不做 | 原因 | 如果你需要 |
|---|---|---|
| 自动交易 | 「选股 + 触达」边界——让用户决策 | 自己接券商 API(谨慎) |
| 实时行情 | 分钟级 / Tick 级别需要「完全不同的架构」 | 接 Tushare / Wind(重数据) |
| 回测系统 | 「历史回测」与「每日选股」工程差异大 | 用 backtrader / vectorbt |
| 机器学习预测 | 选股 ≠ 预测——信号与预测是两件事 | 自行扩展策略层 |
| 多账户支持 | 选股系统不需要区分账户——所有用户看同一份结果 | 加一层「用户路由」 |
| Web 管理界面 | 选股系统不需要交互——自动化跑即可 | 自己加 Flask/FastAPI |
「不做」是工程克制的体现——**让系统聚焦在「做精」而不是「做全」。
虽然 Sequoia-X 设计良好,但有明确局限:
| 局限 | 影响 | 缓解 |
|---|---|---|
| 依赖 baostock 行情稳定性 | 偶尔数据延迟 / 缺失 | 加重试 + 手动补救 |
| 回测能力弱 | 无法验证策略历史表现 | 跑一段时间后自己统计 |
| 没有仓位管理 | 选股 ≠ 仓位 | 自己结合凯利公式等 |
| 没有止损止盈 | 不适合作为「自动交易」前置 | 用户自己决策 |
| 单实例部署 | 无法横向扩展 | 单实例就够 5000+ 只股票 |
| 没有用户系统 | 所有人看同一份结果 | 加一层「用户路由」 |
「局限」是系统边界的诚实标注——让用户预期合理。
Sequoia-X 的架构思想可以迁移到自己的项目:
| 思想 | 你能用在哪 |
|---|---|
| 抽象基类 + 列表注册 | 任何「多实现 + 统一调用」场景:爬虫、报表、ETL 任务 |
| 三层异常隔离 | 任何需要长期运行的服务 |
| 属性测试守护不变量 | 任何关键路径:数据校验、配置加载、API 调用 |
| pydantic-settings + 动态前缀 | 任何配置项可能扩展的项目 |
| rich 日志 + 幂等 logger | 任何需要可读终端输出的脚本 |
| crontab + 日志重定向 | 任何Linux 定时任务 |
「Sequoia-X 思想」=「清晰的边界 + 简单的扩展 + 严格的守护」。
下面这段代码完整演示「在 Sequoia-X 框架上加一个新策略」的完整流程:
# extend_strategy_demo.py # 可运行:在框架中加一个新策略 from abc import ABC, abstractmethod # === 复用第 5 章的策略基类 === class BaseStrategy(ABC): webhook_key: str = "default" def __init__(self, name: str) -> None: self.name = name @abstractmethod def run(self) -> list[str]: ... # === 已有 2 套策略(模拟) === class TurtleStrategy(BaseStrategy): webhook_key = "turtle" def run(self) -> list[str]: return ["600519", "000001"] class MaVolumeStrategy(BaseStrategy): webhook_key = "ma_volume" def run(self) -> list[str]: return ["300750"] # === 新增策略:MACD 金叉 === class MacdStrategy(BaseStrategy): """MACD 金叉策略:EMA12 上穿 EMA26(教学示例)。""" webhook_key = "macd" # 新的 webhook 标识 def run(self) -> list[str]: return ["688981", "002415"] # 模拟选股结果 # === 主程序入口:仅追加一行 === def run_all(strategies: list) -> None: for s in strategies: try: symbols = s.run() print(f"✅ {s.name}(webhook={s.webhook_key})→ {symbols}") except Exception as e: print(f"❌ {s.name} 异常:{e}") if __name__ == "__main__": strategies = [ TurtleStrategy("海龟突破"), MaVolumeStrategy("均线金叉"), MacdStrategy("MACD 金叉"), # ← 新增 1 行 ] run_all(strategies)
预期输出:
✅ 海龟突破(webhook=turtle)→ ['600519', '000001'] ✅ 均线金叉(webhook=ma_volume)→ ['300750'] ✅ MACD 金叉(webhook=macd)→ ['688981', '002415']
加新策略的总成本:
- 写新策略类 ~30 行
- 列表里追加 1 行
- 配置可加 STRATEGY_WEBHOOK_MACD=...(可选)
如果你想「复刻 Sequoia-X 风格」做自己的项目,可以按这张清单来:
| 步骤 | 做什么 | Sequoia-X 的参照 |
|---|---|---|
| 1 | 明确边界 | 「选股 + 触达」,不自动交易 |
| 2 | 三层架构 | 数据层 / 策略层 / 触达层,单向依赖 |
| 3 | 数据层 | 本地存储 + 增量同步 + 断点续传 |
| 4 | 策略层 | 抽象基类 + 列表注册 + 向量化 |
| 5 | 触达层 | 结构化消息 + 多渠道路由 + 失败容错 |
| 6 | 配置 | pydantic-settings + 动态前缀 + fail-fast |
| 7 | 日志 | rich + 命名 logger + 幂等性 |
| 8 | 测试 | hypothesis 属性测试守护不变量 |
| 9 | 部署 | crontab + 日志重定向 + 异常通知 |
「九步复刻」——把 Sequoia-X 思想迁移到任何项目。
到这里,全教程的 9 章 30 节已经走完。让我用一张图回顾整套学习路径:
第 1 章:认识 Sequoia-X ── 全局地图 + 方法论 │ 第 2 章:环境与首轮回填 ── 装环境 + 灌数据 │ 第 3 章:数据引擎精讲 ── baostock + SQLite + 多进程 │ 第 4 章:工程基建 ── 配置 + 日志 │ 第 5 章:策略框架 ── 抽象基类 + 向量化 │ 第 6 章:六大技术面策略 ── 海龟 / 均线 / 旗形 / 洗盘 / 跌停 / RPS │ 第 7 章:事件驱动 + 消息推送 ── 定增公告 + 飞书卡片 │ 第 8 章:主流程编排 ── 双模式 + 异常隔离 │ 第 9 章:质量保障 + 生产 ── 属性测试 + crontab + 扩展方向
Sequoia-X 风格的核心:
清晰的边界、简单的扩展、严格的守护、克制的工程。
愿你带着这套思想,做出属于你自己的、有工程美感的系统。
| 章节 | 子节数 | 主题 |
|---|---|---|
| 01 认识 Sequoia-X | 3 | 定位 / 方法论 / 架构 |
| 02 环境与首轮回填 | 3 | 安装 / 配置 / 回填 |
| 03 数据引擎精讲 | 4 | 选型 / 复权 / 存储 / 增量 |
| 04 工程基建 | 2 | 配置 / 日志 |
| 05 策略框架 | 3 | 抽象 / 向量化 / 注册 |
| 06 六大技术面策略 | 6 | 海龟 / 均线 / 旗形 / 洗盘 / 跌停 / RPS |
| 07 事件驱动与消息推送 | 4 | 定增 / 卡片 / 路由 / 触达 |
| 08 主流程编排 | 2 | 双模式 / 推送编排 |
| 09 质量保障与生产 | 3 | 属性测试 / 部署 / 扩展 |
| 合计 | 30 |
30 节正文 + 9 个支柱页 + 1 份总纲 + 6 张配图 + 15 段可运行示例——一套从零到生产的完整教程。
感谢你的阅读。愿这套系统既教你看懂 Sequoia-X,也带给你**「做工程」**的思考方式。