系统架构设计:四层架构的实战拆解

做量化投资系统,说白了就是搭一套能自动赚钱的流水线。我见过太多人一上来就写策略代码,结果数据源一换、交易接口一改,整个系统就崩了。嗯,这就是架构没想清楚。

今天咱们聊聊《虚拟投资沙盘》的核心骨架——四层架构。我个人习惯把系统拆成数据层、策略层、执行层、分析层。每一层各司其职,互不干扰。你想想看,这样改一个模块,其他模块完全不用动,多省心。

核心原则:高内聚、低耦合。每一层只做自己的事,别越界。

虚拟投资沙盘 · 四层架构图 数据层 数据源接入 · 清洗 · 对齐 · 存储 Yahoo Finance / 本地CSV / 数据库 策略层 信号生成 · 策略逻辑 · 参数管理 均线策略 / 动量策略 / 自定义策略 执行层 订单管理 · 仓位控制 · 交易调度 Backtrader Broker / 模拟撮合 分析层 绩效评估 · 风险分析 · 可视化 夏普比率 / 最大回撤 / 收益曲线

一、数据层:地基不牢,地动山摇

数据层是整个系统的命根子。我在项目中遇到过最惨的事——策略回测跑了一个月,结果发现数据里有三天是重复的,收益率直接虚高20%。从那以后,我每次做数据清洗都格外小心。

数据层主要干三件事:

  • 数据源接入:支持多种来源。我个人习惯用 yfinance 拉美股数据,A股用本地CSV或者从Wind导出的文件。别只依赖一个源,万一挂了就抓瞎。
  • 数据清洗与对齐:缺失值处理、复权价格计算、时间戳对齐。说白了,就是让数据「干干净净、整整齐齐」。
  • 数据存储:小项目用CSV或Parquet,大了上SQLite或PostgreSQL。别一上来就上大数据框架,没必要。

我的小技巧:数据层单独写一个 DataLoader 类,所有策略都通过它拿数据。这样哪天换数据源,只改这一个类就行。

二、策略层:策略是灵魂,但别太花哨

策略层是大家最关心的部分。但说实话,我见过太多人把策略写得跟天书一样,结果回测一跑,还不如简单均线。

策略层要遵循几个原则:

  • 信号与执行分离:策略只负责生成买卖信号(比如金叉买入、死叉卖出),不负责下单。这样换策略时,执行层完全不用动。
  • 参数可配置:别把参数写死在代码里。用配置文件或者参数类管理,方便做参数优化。
  • 策略模板化:我习惯写一个 BaseStrategy 基类,所有策略继承它。这样新策略只需要实现 next() 方法就行。
# 一个简单的策略模板示例
class BaseStrategy:
    def __init__(self, data, params):
        self.data = data
        self.params = params
    
    def next(self, idx):
        """每根K线调用一次,返回信号"""
        raise NotImplementedError

class MaCrossStrategy(BaseStrategy):
    def next(self, idx):
        if self.data['ma5'][idx] > self.data['ma20'][idx]:
            return 'buy'
        elif self.data['ma5'][idx] < self.data['ma20'][idx]:
            return 'sell'
        return 'hold'

三、执行层:把信号变成真金白银

执行层负责把策略的信号变成真实的交易。这里坑最多。我曾经在实盘里遇到过信号发出来了,但执行层因为滑点没成交,结果策略曲线和实盘曲线差了一大截。

执行层核心模块:

模块 职责 技术选型建议
订单管理 接收信号,生成订单,管理订单状态 Backtrader 内置 Broker
仓位控制 根据资金和风险计算下单数量 自定义 PositionManager
交易调度 处理订单排队、撮合、滑点模拟 Backtrader 的 CommissionScheme
日志记录 记录每一笔交易的详细信息 Python logging + CSV

注意:回测时一定要模拟滑点和手续费。我见过有人回测年化50%,加上千分之一手续费后直接变成20%。别让回测骗了你。

四、分析层:用数据说话

分析层是最后一步,但也是最重要的一步。策略好不好,不是看曲线漂不漂亮,而是看风险调整后的收益。

我一般会算这几个指标:

  • 年化收益率:别只看总收益,时间维度很重要。
  • 最大回撤:这个指标比收益率更关键。回撤超过30%的策略,一般人拿不住。
  • 夏普比率:衡量每单位风险获得的超额收益。大于1算及格,大于2算优秀。
  • 胜率与盈亏比:胜率高不一定赚钱,盈亏比高才是王道。

可视化方面,我习惯用 matplotlib 画收益曲线和回撤曲线。Backtrader 自带的绘图功能也够用,但如果你想做更炫酷的交互式图表,可以试试 plotly

五、技术选型:为什么是 Python + Pandas + Backtrader?

这个问题我经常被问到。说实话,选型没有绝对的对错,只有合不合适。

  • Python:生态丰富,社区活跃。做量化投资,Python 是绕不开的语言。C++ 快是快,但开发效率差太多了。
  • Pandas:处理时间序列数据的神器。数据清洗、对齐、计算指标,一行代码搞定。我每天跟 Pandas 打交道,它就像我的左膀右臂。
  • Backtrader:开源回测框架里最成熟的之一。支持多策略、多数据源、自定义指标,而且文档齐全。我用了三年,没出过大问题。

我的建议:初学者先用 Backtrader 跑通全流程,等熟悉了再考虑自己写框架。别一开始就想着造轮子,先学会用轮子。

六、模块划分原则:别让代码变成一锅粥

模块划分这件事,说白了就是「把大象装进冰箱分几步」。我总结了几条原则:

  1. 单一职责:一个模块只做一件事。数据模块别管策略,策略模块别管下单。
  2. 接口清晰:模块之间通过接口通信,别直接调用内部函数。比如策略层只输出信号字典,执行层只接收信号字典。
  3. 可替换性:每个模块都应该能独立替换。今天用 Backtrader,明天想换 Zipline,改一个模块就行。
  4. 配置驱动:所有参数都放在配置文件里,别硬编码。这样调参时不用改代码,改配置文件就行。

嗯,以上就是系统架构设计的核心内容。记住,架构设计不是为了炫技,而是为了让你的系统更稳定、更易维护、更容易迭代。下一章咱们开始动手写代码,从数据层开始,一步步搭建你的虚拟投资沙盘。


公众号:蓝海资料掘金营,微信deep3321