30 KiB
QSForex 详细说明文档
一、项目简介
QSForex 是一个开源的、基于事件驱动架构的外汇(Forex)量化交易系统,支持回测和实盘交易。项目由 QuantStart.com 创始人 Michael Halls-Moore 于 2015 年开发,采用 MIT 开源许可证,目前处于 "alpha" 阶段。
核心特性
| 特性 | 说明 |
|---|---|
| 事件驱动架构 | 回测与实盘使用同一套事件接口,策略无需修改即可从回测切换到实盘 |
| Tick 级精度 | 支持逐 tick 级别的多日、多货币对回测 |
| 交易成本 | 回测中默认包含点差(Spread)成本 |
| 多货币对 | 支持同时交易多个货币对 |
| 实盘交易 | 通过 OANDA Brokerage API 进行实盘交易 |
| 绩效分析 | 支持权益曲线、收益率、最大回撤等指标计算与可视化 |
| 单元测试 | 核心计算逻辑有完整的单元测试覆盖 |
二、项目目录结构
qsforex/
├── __init__.py # 顶层包入口
├── settings.py # 全局配置(OANDA 凭证、数据路径、杠杆等)
├── logging.conf # 日志配置
├── requirements.txt # Python 依赖包列表
│
├── event/ # ====== 事件系统(核心通信机制) ======
│ ├── __init__.py
│ └── event.py # 定义 TickEvent / SignalEvent / OrderEvent
│
├── data/ # ====== 数据层 ======
│ ├── __init__.py
│ ├── price.py # 历史 CSV 数据读取器(回测用)
│ └── streaming.py # OANDA Streaming API 实时数据流(实盘用)
│
├── strategy/ # ====== 策略层 ======
│ ├── __init__.py
│ └── strategy.py # TestStrategy + MovingAverageCrossStrategy
│
├── portfolio/ # ====== 组合与仓位管理 ======
│ ├── __init__.py
│ ├── portfolio.py # 资金管理、风险控制、信号执行
│ ├── position.py # 单个仓位的 P&L 计算
│ ├── portfolio_test.py # 组合模块单元测试
│ └── position_test.py # 仓位模块单元测试
│
├── execution/ # ====== 执行层 ======
│ ├── __init__.py
│ └── execution.py # SimulatedExecution + OANDAExecutionHandler
│
├── backtest/ # ====== 回测引擎 ======
│ ├── __init__.py
│ ├── backtest.py # Backtest 主循环
│ └── output.py # 可视化输出(权益曲线、回撤图)
│
├── performance/ # ====== 绩效计算 ======
│ ├── __init__.py
│ └── performance.py # 最大回撤(MDD)计算
│
├── trading/ # ====== 实盘交易 ======
│ ├── __init__.py
│ └── trading.py # 多线程实时交易循环
│
├── examples/ # ====== 示例 ======
│ ├── __init__.py
│ └── mac.py # 移动平均线交叉策略回测示例
│
└── scripts/ # ====== 辅助脚本 ======
├── generate_simulated_pair.py # 生成模拟外汇 tick 数据
└── test_performance.py # 绩效计算调试脚本
三、事件驱动架构详解
3.1 概述
整个系统围绕一个事件队列(Event Queue) 运转。事件是系统中各组件之间通信的唯一方式。这种设计使得各模块高度解耦,策略代码在回测和实盘之间无需修改即可复用。
3.2 事件类型
系统定义了三种事件,按处理顺序依次流转:
数据源 → TickEvent → 策略 → SignalEvent → 组合 → OrderEvent → 执行引擎
TickEvent(行情事件)
由数据层产生,包含市场报价信息。
class TickEvent(Event):
def __init__(self, instrument, time, bid, ask):
self.type = 'TICK'
self.instrument = instrument # 货币对,如 "GBPUSD"
self.time = time # 时间戳
self.bid = bid # 买价
self.ask = ask # 卖价
SignalEvent(信号事件)
由策略层产生,表示一个交易决策。
class SignalEvent(Event):
def __init__(self, instrument, order_type, side, time):
self.type = 'SIGNAL'
self.instrument = instrument # 货币对
self.order_type = order_type # 订单类型(当前仅支持 "market")
self.side = side # 方向:"buy" 或 "sell"
self.time = time # 产生信号的 tick 时间
OrderEvent(订单事件)
由组合层产生,表示一个需要发送到经纪商的实际订单。
class OrderEvent(Event):
def __init__(self, instrument, units, order_type, side):
self.type = 'ORDER'
self.instrument = instrument # 货币对
self.units = units # 交易数量
self.order_type = order_type # 订单类型
self.side = side # 方向
3.3 事件流向图
┌──────────────┐
│ 数据源 │
│ (CSV/OANDA) │
└──────┬───────┘
│ TickEvent
▼
┌───────────────────────┐
│ 事件队列 (Queue) │
└───────┬───────────────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 策略 │ │ 组合 │ │ 执行 │
│ (Strategy)│ │(Portfolio)│ │(Execution)│
└─────┬────┘ └─────┬────┘ └──────────┘
│ │
│ SignalEvent │ OrderEvent
└─────────────┘
(放回事件队列)
四、各模块详细说明
4.1 数据层(data/)
4.1.1 PriceHandler(抽象基类)
所有数据处理器继承自 PriceHandler,提供以下核心功能:
_set_up_prices_dict():构建价格字典,同时维护正向和反向汇率对。例如,当交易GBPUSD时,系统自动计算并维护USDGBP的 bid/ask,用于跨货币对的盈亏换算。invert_prices():将 bid/ask 价格取倒数,生成反向汇率对。
4.1.2 HistoricCSVPriceHandler(历史数据处理器)
用于回测场景,从 CSV 文件读取历史 tick 数据。
数据格式:兼容 DukasCopy Historical Data Feed 格式,文件名格式为 {货币对}_{YYYYMMDD}.csv,例如 GBPUSD_20140112.csv。
CSV 文件内部格式:
Time,Ask,Bid,AskVolume,BidVolume
12.01.2014 22:00:10.123,1.50200,1.50180,1.50,1.50
处理流程:
- 扫描
CSV_DATA_DIR目录下所有符合格式的 CSV 文件 - 提取所有日期,去重排序
- 按天加载数据,使用 Pandas 将多个货币对的数据按时间合并排序
stream_next_tick()方法每次被调用时,按时间顺序输出下一个 tick- 每输出一个 tick,同时更新正向和反向汇率对的价格
4.1.3 StreamingForexPrices(实时数据流处理器)
用于实盘交易场景,通过 OANDA 的 Streaming API 获取实时价格。
处理流程:
- 建立到 OANDA streaming 端点的 HTTPS 连接
- 使用
requests.Session的流式传输持续接收数据 - 逐行解析 JSON 格式的 tick 数据
- 生成
TickEvent放入事件队列 - 同步更新正向和反向汇率对价格
4.2 策略层(strategy/)
策略层负责从 TickEvent 中分析市场数据,产生交易信号。所有策略必须实现 calculate_signals(event) 方法。
4.2.1 TestStrategy(测试策略)
简单的测试策略,每 5 个 tick 交替买入/卖出。设计目的是持续"穿越点差",因此必然亏损,仅用于验证系统运行是否正常。
逻辑:
tick 0-4: 无操作
tick 5: BUY → 持仓
tick 10: SELL → 平仓
tick 15: BUY → 持仓
...循环
4.2.2 MovingAverageCrossStrategy(双均线交叉策略)
经典的移动平均线交叉策略,仅做多。
参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
short_window |
500 | 短期 SMA 窗口(tick 数) |
long_window |
2000 | 长期 SMA 窗口(tick 数) |
信号逻辑:
- 短期 SMA 上穿长期 SMA 且未持仓 → 产生
BUY信号(开多仓) - 短期 SMA 下穿长期 SMA 且已持仓 → 产生
SELL信号(平多仓)
性能优化:使用滚动 SMA 算法,避免每次重新计算完整均线:
def calc_rolling_sma(self, sma_m_1, window, price):
return ((sma_m_1 * (window - 1)) + price) / window
该算法将时间复杂度从 O(n) 降为 O(1)。
多货币对支持:通过 pairs_dict 为每个货币对维护独立的 tick 计数、持仓状态和 SMA 值。
4.3 组合与仓位管理(portfolio/)
4.3.1 Position(仓位类)
管理单个货币对的交易仓位,支持多空双向。
核心属性:
| 属性 | 说明 |
|---|---|
home_currency |
账户计价货币(如 GBP) |
position_type |
仓位方向:"long" 或 "short" |
currency_pair |
交易货币对(如 EURUSD) |
units |
持仓数量 |
avg_price |
平均持仓成本 |
cur_price |
当前市场价格 |
profit_base |
以计价货币计算的浮动盈亏 |
profit_perc |
浮动盈亏百分比 |
关键方法:
| 方法 | 说明 |
|---|---|
calculate_pips() |
计算当前盈亏点数 |
calculate_profit_base() |
计算以账户货币计价的盈亏金额 |
update_position_price() |
更新当前价格并重新计算盈亏 |
add_units(units) |
加仓,重新计算平均成本 |
remove_units(units) |
减仓,返回已实现盈亏 |
close_position() |
平仓,返回已实现盈亏 |
跨货币对换算:对于 EUR/USD 仓位,账户以 GBP 计价时的盈亏计算:
Profit_GBP = Pips × USD/GBP_Rate × Units
4.3.2 Portfolio(组合类)
管理整个交易组合,负责资金管理、风险控制和信号执行。
核心属性:
| 属性 | 默认值 | 说明 |
|---|---|---|
equity |
100,000.00 | 账户总权益 |
balance |
= equity | 当前余额 |
leverage |
20 | 杠杆倍数 |
risk_per_trade |
0.02 (2%) | 单笔交易风险比例 |
trade_units |
equity × 0.02 | 单笔交易头寸规模 |
关键方法:
| 方法 | 说明 |
|---|---|
calc_risk_position_size() |
计算基于风险的仓位大小 |
add_new_position() |
创建新仓位 |
add_position_units() |
对已有仓位加仓 |
remove_position_units() |
对已有仓位减仓 |
close_position() |
平掉整个仓位 |
update_portfolio(tick_event) |
更新所有持仓的浮动盈亏 |
execute_signal(signal_event) |
执行交易信号,生成 OrderEvent |
output_results() |
输出回测结果到 CSV |
create_equity_file() |
创建回测结果 CSV 文件 |
信号执行逻辑 execute_signal:
| 信号方向 | 当前仓位 | 动作 |
|---|---|---|
buy |
无仓位 | 创建多头仓位 |
buy |
有多头仓位 | 加仓 |
buy |
有空头仓位 | 若 units 相等则平仓 |
sell |
无仓位 | 创建空头仓位 |
sell |
有多头仓位 | 若 units 相等则平仓 |
sell |
有空头仓位 | 加仓 |
4.4 执行层(execution/)
4.4.1 ExecutionHandler(抽象基类)
定义了 execute_order() 接口,所有执行处理器必须实现此方法。
4.4.2 SimulatedExecution(模拟执行)
回测模式下的执行器,execute_order() 方法为空操作。实际的成交处理由 Portfolio 对象直接完成。
4.4.3 OANDAExecutionHandler(OANDA 执行器)
实盘模式下的执行器,通过 OANDA REST API 发送订单。
下单流程:
- 建立到 OANDA API 域名的 HTTPS 连接
- 构造 HTTP POST 请求,包含认证信息和订单参数
- 发送到
/v1/accounts/{account_id}/orders端点 - 记录 API 响应日志
4.5 回测引擎(backtest/)
4.5.1 Backtest 类
回测引擎的核心类,将所有组件组装在一起运行回测。
初始化参数:
| 参数 | 说明 |
|---|---|
pairs |
交易货币对列表 |
data_handler |
数据处理器类(如 HistoricCSVPriceHandler) |
strategy |
策略类(如 MovingAverageCrossStrategy) |
strategy_params |
策略参数字典 |
portfolio |
组合管理类 |
execution |
执行处理器类 |
equity |
初始资金 |
heartbeat |
事件循环心跳间隔(秒) |
max_iters |
最大迭代次数 |
回测主循环 _run_backtest():
while iters < max_iters and ticker.continue_backtest:
try:
event = events.get(False) # 非阻塞获取事件
except queue.Empty:
ticker.stream_next_tick() # 没有事件则推进下一个 tick
else:
if event.type == 'TICK':
strategy.calculate_signals(event) # 策略分析
portfolio.update_portfolio(event) # 更新盈亏
elif event.type == 'SIGNAL':
portfolio.execute_signal(event) # 执行信号
elif event.type == 'ORDER':
execution.execute_order(event) # 执行订单
time.sleep(heartbeat)
iters += 1
关键设计:当事件队列为空时,主动从数据源获取下一个 tick 并放入队列,而非等待。这种"拉取"模式确保回测的确定性和可复现性。
4.5.2 可视化输出
读取 equity.csv 文件,使用 Matplotlib + Seaborn 绘制三张图表:
- 权益曲线(上图):组合价值随时间变化
- 期间收益率(中图):每个 tick 的收益率
- 回撤曲线(下图):从历史高点的回撤幅度
4.6 绩效计算(performance/)
create_drawdowns(pnl) 函数:
- 计算权益曲线的峰值到谷值的最大回撤(Maximum Drawdown, MDD)
- 计算回撤持续时间
- 返回
(drawdown_series, max_drawdown, max_duration)
4.7 实盘交易(trading/)
实盘交易的入口,使用双线程架构:
线程 1(价格流): StreamingForexPrices.stream_to_queue()
└── 持续从 OANDA 接收实时价格,生成 TickEvent 放入队列
线程 2(交易循环): trade()
└── 从队列获取事件 → 策略 → 组合 → 执行
五、配置文件说明
5.1 settings.py
# OANDA 环境配置
ENVIRONMENTS = {
"streaming": {
"real": "stream-fxtrade.oanda.com",
"practice": "stream-fxpractice.oanda.com",
"sandbox": "stream-sandbox.oanda.com"
},
"api": {
"real": "api-fxtrade.oanda.com",
"practice": "api-fxpractice.oanda.com",
"sandbox": "api-sandbox.oanda.com"
}
}
# 数据目录和输出目录(从环境变量读取)
CSV_DATA_DIR = os.environ.get('QSFOREX_CSV_DATA_DIR', None)
OUTPUT_RESULTS_DIR = os.environ.get('QSFOREX_OUTPUT_RESULTS_DIR', None)
# 交易环境选择
DOMAIN = "practice" # "practice" / "real" / "sandbox"
# OANDA 认证
ACCESS_TOKEN = os.environ.get('OANDA_API_ACCESS_TOKEN', None)
ACCOUNT_ID = os.environ.get('OANDA_API_ACCOUNT_ID', None)
# 账户设置
BASE_CURRENCY = "GBP" # 账户基础货币
EQUITY = Decimal("100000.00") # 初始资金
5.2 logging.conf
配置了 root logger 和 qsforex.trading.trading logger,均输出到控制台,级别为 DEBUG。
六、使用流程
6.1 回测流程
步骤 1: 生成模拟数据
└── python scripts/generate_simulated_pair.py GBPUSD
步骤 2: 运行回测
└── python examples/mac.py
步骤 3: 查看结果
└── python backtest/output.py
6.2 实盘交易流程
步骤 1: 配置 OANDA 凭证(settings.py)
步骤 2: 编写策略(继承策略基类)
步骤 3: 启动交易
└── python trading/trading.py
七、技术栈
| 类别 | 依赖包 | 版本 |
|---|---|---|
| 数值计算 | numpy | 1.9.2 |
| 科学计算 | scipy | 0.15.1 |
| 数据处理 | pandas | 0.16.1 |
| 可视化 | matplotlib | 1.4.3 |
| 统计可视化 | seaborn | 0.5.1 |
| 机器学习 | scikit-learn | 0.16.1 |
| HTTP 请求 | requests | 2.7.0 |
| 测试框架 | nose | 1.3.6 |
| Mock | mock | 1.0.1 |
| 交互环境 | ipython | 3.1.0 |
八、已知问题与改进建议
8.1 兼容性问题
| 问题 | 严重程度 | 说明 |
|---|---|---|
| Python 2.7 语法 | 高 | 使用 from __future__、try: import Queue、__metaclass__ 等旧式写法,无法在 Python 3 上直接运行 |
| 依赖版本过旧 | 高 | pandas 0.16、numpy 1.9 发布于 2015 年,存在安全漏洞 |
| OANDA API 版本 | 高 | 使用 OANDA v1 API,该版本已被废弃,需迁移到 v3 REST API |
8.2 代码缺陷
| 问题 | 位置 | 说明 |
|---|---|---|
缺少 self. 前缀 |
portfolio.py L165 | add_position_units 应为 self.add_position_units,会导致 NameError |
| 无 setup.py | 根目录 | 缺少标准的 Python 包安装配置,无法通过 pip install 安装 |
| 硬编码 | generate_simulated_pair.py | 模拟数据生成的日期、初始价格等参数硬编码 |
8.3 改进建议
- Python 3 迁移:将所有语法升级到 Python 3.6+,移除
from __future__导入 - 依赖更新:升级到最新版本的 pandas、numpy 等核心依赖
- API 升级:将 OANDA API 从 v1 迁移到 v3
- 包管理现代化:添加
setup.py或pyproject.toml - Bug 修复:修复 portfolio.py 中缺失
self.的问题 - 配置外部化:将模拟数据生成参数从硬编码改为配置文件或命令行参数
九、扩展指南
9.1 编写自定义策略
只需继承或模仿现有策略,实现 calculate_signals(event) 方法:
class MyCustomStrategy(object):
def __init__(self, pairs, events):
self.pairs = pairs
self.events = events
# 初始化你的策略状态
def calculate_signals(self, event):
if event.type == 'TICK':
# 你的策略逻辑
# 当满足条件时,生成 SignalEvent
signal = SignalEvent(pair, "market", "buy", event.time)
self.events.put(signal)
然后在回测或实盘入口中替换策略类即可。
9.2 添加新的数据源
继承 PriceHandler 基类,实现数据获取和 stream_next_tick() 方法。
十、许可证
MIT License - Copyright (c) 2015 Michael Halls-Moore
风险提示:外汇保证金交易具有高风险,可能不适合所有投资者。过去的表现不代表未来的结果。高杠杆可能对您不利也可能对您有利。在决定投资外汇之前,您应仔细考虑您的投资目标、经验水平和风险承受能力。
十一、可复用模块分析 —— 多项目整合视角
本章节专门为综合多个项目构建自有交易系统的开发者编写,帮助你快速识别 QSForex 中最值得借鉴和复用的模块,以及它在多项目组合中的定位。
11.1 本项目在量化交易系统中的定位
QSForex 的核心价值在于轻量级、教学友好、架构清晰。它不是一个功能完备的生产级系统,而是一个架构原型——用最少的代码完整展示了事件驱动交易系统的骨架。在多项目整合中,QSForex 适合作为:
| 角色 | 说明 |
|---|---|
| 架构参考蓝图 | 事件驱动模式是量化交易系统的主流范式,本项目的实现简洁易懂 |
| 快速原型验证 | 当你有一个新策略想法时,可以最快速度搭出回测环境 |
| 教学/入门材料 | 代码量小、注释清晰,适合团队新成员快速理解量化系统全貌 |
11.2 模块可复用性矩阵
以下按照可复用价值从高到低排列,并标注每个模块在多项目整合中的建议处理方式。
⭐⭐⭐⭐⭐ 强烈推荐复用/借鉴
| 模块 | 核心价值 | 可复用部分 | 跨市场适用性 |
|---|---|---|---|
| 事件驱动架构 | ⭐⭐⭐⭐⭐ | 整个事件队列 + 事件类型设计 | 股票/期货/加密货币均可 |
| 回测引擎 | ⭐⭐⭐⭐⭐ | Backtest._run_backtest() 主循环 |
通用,只需替换数据源 |
| 仓位管理 | ⭐⭐⭐⭐⭐ | Position 类的盈亏计算逻辑 |
外汇特有,但多空双向模式通用 |
| 滚动 SMA 算法 | ⭐⭐⭐⭐ | calc_rolling_sma() 高效增量计算 |
所有时间序列策略通用 |
详细分析
① 事件驱动架构(最核心的复用价值)
事件类型设计 → 事件队列 → 事件分发循环
这是 QSForex 的灵魂。无论你最终使用什么市场、什么语言、什么数据库,这个三层解耦的模式是量化交易系统的事实标准:
数据层 ──TickEvent──→ 策略层 ──SignalEvent──→ 组合层 ──OrderEvent──→ 执行层
↑ ↑ ↑ ↑
可替换 可替换 可替换 可替换
迁移建议:
- 保留事件类型定义(TickEvent / SignalEvent / OrderEvent),按需扩展(如增加
FillEvent、RiskEvent) - 保留事件队列 +
while循环分发的模式 - 替换各层具体实现即可适配任何市场
② 回测引擎主循环
backtest.py 中的 _run_backtest() 方法是经典的回测主循环模式:
while iters < max_iters and ticker.continue_backtest:
try:
event = events.get(False) # 非阻塞取事件
except queue.Empty:
ticker.stream_next_tick() # 无事件时推进数据
else:
if event.type == 'TICK':
strategy.calculate_signals(event)
portfolio.update_portfolio(event)
elif event.type == 'SIGNAL':
portfolio.execute_signal(event)
elif event.type == 'ORDER':
execution.execute_order(event)
迁移建议:
- 这个循环结构可以直接移植到任何市场(股票、期货、加密货币)
- 只需实现对应市场的
PriceHandler子类即可 - 可以扩展为支持
BarEvent(K线事件)以适配日线级别策略
③ 仓位盈亏计算
position.py 中的 Position 类实现了完整的:
- 多空双向持仓
- 平均成本计算(加仓/减仓时重新计算)
- 已实现/未实现盈亏分离
- 跨货币换算
迁移建议:
- 外汇特有的汇率换算部分可以剥离,核心的
avg_price加权平均算法是通用的 - 期货/股票场景下,需增加保证金计算、合约乘数等字段
- 加密货币场景几乎可以直接复用
④ 滚动 SMA 增量算法
strategy.py 中的高效均线计算:
def calc_rolling_sma(self, sma_m_1, window, price):
return ((sma_m_1 * (window - 1)) + price) / window
这个算法将 SMA 计算从 O(n) 优化到 O(1),在高频回测中效果显著。
⭐⭐⭐ 可借鉴思路,需重新实现
| 模块 | 核心价值 | 需改造的原因 |
|---|---|---|
| 数据层 | CSV 多文件按天加载、多货币对按时间归并 | 格式绑定 DukasCopy,且 Python 2.7 的 pandas 语法已过时 |
| 信号执行逻辑 | buy/sell 与多空仓位的状态机 | 逻辑有 Bug(缺少 self.),且不支持部分平仓 |
| 绩效计算 | 最大回撤计算 | 实现过于简单,现代系统需要 Sharpe/Sortino/Calmar 等 |
| 可视化输出 | 三图布局(权益+收益+回撤) | matplotlib 版本过旧,可用 plotly/bokeh 替换 |
⭐⭐ 参考价值有限,建议替换
| 模块 | 原因 |
|---|---|
| OANDA 执行器 | 使用已废弃的 OANDA v1 API,必须用 v3 重写或换经纪商 |
| 实时数据流 | 同上,API 版本过时 |
| 模拟数据生成 | 仅生成随机游走数据,无市场微观结构,建议用专业回测数据源 |
| 日志配置 | 可用 structlog 或 loguru 替代 |
11.3 多项目整合的推荐架构
如果你正在综合多个项目构建自己的交易系统,推荐的分层架构如下:
┌─────────────────────────────────────────────────────┐
│ 策略层 (Strategy) │
│ 从 QSForex 借鉴:事件接口 + calculate_signals │
│ 从其他项目借鉴:因子计算、ML模型、信号组合 │
├─────────────────────────────────────────────────────┤
│ 组合层 (Portfolio) │
│ 从 QSForex 借鉴:多空仓位管理 + 风险头寸计算 │
│ 从其他项目借鉴:凯利公式、VaR、组合优化 │
├─────────────────────────────────────────────────────┤
│ 执行层 (Execution) │
│ 从 QSForex 借鉴:SimulatedExecution(回测模式) │
│ 从其他项目借鉴:多经纪商适配、订单路由、智能下单 │
├─────────────────────────────────────────────────────┤
│ 数据层 (Data) │
│ 从 QSForex 借鉴:多标的按时间归并的思想 │
│ 从其他项目借鉴:实时数据库、数据清洗、复权处理 │
├─────────────────────────────────────────────────────┤
│ 事件总线 (Event Bus) │
│ 从 QSForex 借鉴:Events Queue + 事件类型体系 ★★★ │
│ 从其他项目借鉴:Redis/Kafka 分布式事件总线 │
└─────────────────────────────────────────────────────┘
11.4 QSForex 在多项目组合中的角色总结
| 维度 | QSForex 的定位 |
|---|---|
| 架构教学 | 🥇 最佳入门教材——事件驱动模式的最简实现 |
| 回测引擎 | 🥈 可作为快速原型验证工具 |
| 策略开发 | 🥈 内置策略简单,但策略接口设计值得参考 |
| 生产就绪度 | ❌ 不适合直接用于生产环境 |
| 跨市场支持 | ❌ 仅外汇,需大量改造才能支持股票/期货 |
| 代码质量 | ⚠️ 有已知 Bug,需要修复后再复用 |
推荐的复用策略:
- 提取事件驱动骨架:将
event/+backtest/的核心循环提取为通用框架 - 修复并提取仓位管理:修复
portfolio.py的 Bug,抽象出通用的Position基类 - 保留策略接口规范:统一
calculate_signals(event)签名作为所有策略的入口规范 - 替换其他所有模块:数据源、执行器、绩效分析、可视化全部用现代方案重新实现
一句话总结:QSForex 的事件驱动架构 + 回测主循环 + 仓位管理是最值得带走的核心资产,其余模块建议用其他项目的更成熟实现替代。