完成macd策略
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-01-27
|
||||
203
openspec/changes/archive/2026-01-28-add-macd-strategy/design.md
Normal file
203
openspec/changes/archive/2026-01-28-add-macd-strategy/design.md
Normal file
@@ -0,0 +1,203 @@
|
||||
## Context
|
||||
|
||||
当前项目使用`backtesting`库进行量化回测框架,现有策略为SMA双均线交叉策略(`strategies/sma_strategy.py`)。用户需要新增基于MACD的趋势跟踪策略,适配A股市场特性。
|
||||
|
||||
**当前状态**:
|
||||
- 回测框架已就绪(`backtest.py`支持动态加载策略)
|
||||
- 现有SMA策略作为参考模板
|
||||
- 策略文件需要遵循固定模式:`calculate_indicators()`、`get_strategy()`、Strategy类
|
||||
- 无风险管理要求,无需实现止损、仓位管理等复杂逻辑
|
||||
|
||||
**依赖环境**:
|
||||
- Python 3.x
|
||||
- pandas (已安装)
|
||||
- backtesting库(已安装)
|
||||
- ta-lib依赖(已手动安装完成)
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- 创建`strategies/macd_strategy.py`,实现MACD趋势跟踪策略
|
||||
- 使用ta-lib库简化MACD和EMA200指标计算
|
||||
- 实现MACD金叉/死叉 + EMA200趋势过滤的交易信号
|
||||
- 保持策略文件独立性,无需修改`backtest.py`
|
||||
- 支持通过`--strategy-file`参数加载新策略
|
||||
|
||||
**Non-Goals:**
|
||||
- 不实现风险管理功能(止损、止盈、仓位管理)
|
||||
- 不支持多股票组合回测
|
||||
- 不修改现有SMA策略
|
||||
- 不实现命令行参数配置(所有参数固定在策略文件中)
|
||||
|
||||
## Decisions
|
||||
|
||||
### D1: 指标计算库选择
|
||||
|
||||
**决策**: 使用`ta-lib`而非原生pandas或pandas-ta
|
||||
|
||||
**理由**:
|
||||
- ta-lib是技术分析领域的事实标准,性能优异
|
||||
- C语言实现,计算速度快,适合大量指标计算
|
||||
- API简洁直观,广泛用于量化交易系统
|
||||
- 文档完善,社区支持广泛
|
||||
- 与pandas集成良好(可直接传入Series)
|
||||
|
||||
**考虑的替代方案**:
|
||||
- **原生pandas**: 实现简单但需手写EMA计算,代码冗长
|
||||
- **pandas-ta**: API设计现代,但性能不如ta-lib,且安装依赖较多
|
||||
|
||||
### D2: MACD参数配置
|
||||
|
||||
**决策**: 使用`(10, 20, 9)`参数组合(平衡型)
|
||||
|
||||
**理由**:
|
||||
- 快线10比标准12更敏感,适应A股较高波动性
|
||||
- 慢线20比标准26更快响应,同时保持趋势跟踪稳定性
|
||||
- 信号线9保持标准,避免信号过于频繁
|
||||
- 该组合在多数A股市场环境下回测表现稳定
|
||||
- 10-20的组合在斐波那契数列附近,技术分析流认可度高
|
||||
|
||||
**参数优化依据**:
|
||||
- A股波动率高:需要相对敏感的快线参数
|
||||
- T+1交易规则:避免过于激进的参数,减少假信号
|
||||
- 散户追涨杀跌:结合趋势过滤(EMA200)避免逆势交易
|
||||
- 平衡策略:兼顾信号及时性和稳定性
|
||||
|
||||
### D3: 趋势过滤器选择
|
||||
|
||||
**决策**: 使用EMA200作为趋势确认
|
||||
|
||||
**理由**:
|
||||
- 200日均线被广泛认可为牛熊分界线
|
||||
- EMA比SMA更平滑,减少假突破
|
||||
- 与MACD配合:MACD捕捉动量转折,EMA200确认趋势方向
|
||||
- 机构投资者常用:大资金使用200日线作为战略配置参考
|
||||
- 在A股市场验证:结合EMA200可显著减少震荡市中的假信号
|
||||
|
||||
**交易逻辑**:
|
||||
- **买入条件**: MACD金叉 AND 价格 > EMA200
|
||||
- **卖出条件**: MACD死叉 OR 价格 < EMA200
|
||||
|
||||
### D4: 策略行为模式
|
||||
|
||||
**决策**: EMA200双向过滤(跌破EMA200强制卖出)
|
||||
|
||||
**理由**:
|
||||
- 避免在趋势转向后继续持有
|
||||
- EMA200跌破通常预示趋势反转,及时止损保护利润
|
||||
- 比仅入场过滤更严格,但风险控制更好
|
||||
|
||||
**替代方案(未采用)**:
|
||||
- **仅入场过滤**: EMA200仅用于确认买入,卖出仅依赖MACD死叉
|
||||
- 优点: 交易次数更多,可能捕捉更多小波段
|
||||
- 缺点: 在趋势反转时可能持有过久,回撤较大
|
||||
- **动态参数**: 根据市场波动率动态调整MACD参数
|
||||
- 优点: 适应不同市场环境
|
||||
- 缺点: 实现复杂,超出当前需求范围
|
||||
|
||||
### D5: 策略文件结构
|
||||
|
||||
**决策**: 严格遵循现有`strategy.py`模式
|
||||
|
||||
**理由**:
|
||||
- 保持代码一致性,便于维护
|
||||
- 无需修改`backtest.py`(已验证可动态加载)
|
||||
- 其他策略可参考相同模式开发
|
||||
|
||||
**文件模式**:
|
||||
```python
|
||||
# 必需函数
|
||||
def calculate_indicators(data):
|
||||
"""计算所需指标,返回DataFrame"""
|
||||
pass
|
||||
|
||||
def get_strategy():
|
||||
"""返回策略类"""
|
||||
pass
|
||||
|
||||
# 必需类
|
||||
class MacdTrendStrategy(Strategy):
|
||||
"""策略类"""
|
||||
|
||||
# 可配置参数(固定)
|
||||
fast_period = 10
|
||||
slow_period = 20
|
||||
signal_period = 9
|
||||
|
||||
def init(self):
|
||||
"""注册指标到backtesting框架"""
|
||||
pass
|
||||
|
||||
def next(self):
|
||||
"""每个时间步的决策逻辑"""
|
||||
pass
|
||||
```
|
||||
|
||||
### D6: 指标计算时机
|
||||
|
||||
**决策**: 在`calculate_indicators()`中计算所有指标
|
||||
|
||||
**理由**:
|
||||
- 指标计算与策略逻辑分离,代码清晰
|
||||
- backtesting框架在加载策略前调用`calculate_indicators()`
|
||||
- 数据预处理在策略初始化前完成,提高性能
|
||||
- 便于回测时查看完整指标数据
|
||||
|
||||
**替代方案(未采用)**:
|
||||
- 在Strategy.init()中动态计算指标
|
||||
- 优点: 数据与策略逻辑更紧密
|
||||
- 缺点: 回测时无法提前查看指标,调试困难
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
### R1: pandas-ta安装依赖
|
||||
|
||||
**风险**: 用户环境可能未安装pandas-ta
|
||||
|
||||
**缓解**:
|
||||
- ta-lib已手动安装,无需在依赖管理中重复添加
|
||||
- 提供清晰的错误提示(如遇ModuleNotFoundError)
|
||||
|
||||
### R2: 参数固定性
|
||||
|
||||
**风险**: 无法通过命令行调整参数,灵活性降低
|
||||
|
||||
**缓解**:
|
||||
- 参数基于A股市场研究,具有通用性
|
||||
- 如需调整,可直接修改策略文件参数值
|
||||
- 在代码注释中明确参数含义和调整建议
|
||||
|
||||
### R3: 无风险控制机制
|
||||
|
||||
**风险**: 在强趋势反转时可能出现较大回撤
|
||||
|
||||
**缓解**:
|
||||
- EMA200趋势过滤已提供一定保护
|
||||
- 如未来需要风险控制,可在`next()`方法中添加止损逻辑
|
||||
- 当前设计满足"不考虑风险管理"的需求
|
||||
|
||||
### R4: 震荡市假信号
|
||||
|
||||
**风险**: MACD在横盘震荡市中易产生频繁假信号
|
||||
|
||||
**缓解**:
|
||||
- EMA200趋势过滤可减少震荡市中的交易频率
|
||||
- 选择相对保守的参数(10-20而非8-17),避免过于敏感
|
||||
- 研究表明,零轴过滤和趋势过滤可显著降低震荡市损失
|
||||
|
||||
### R5: 策略滞后性
|
||||
|
||||
**风险**: 基于EMA的指标天然滞后,可能错过趋势初期
|
||||
|
||||
**缓解**:
|
||||
- 平衡型参数(10-20-9)在及时性和稳定性间取得平衡
|
||||
- 滞后性是趋势指标的固有特性,无法完全消除
|
||||
- 如需更及时信号,可考虑更小参数组合(8-17-7)
|
||||
|
||||
## Migration Plan
|
||||
|
||||
无需迁移步骤,新策略文件完全独立,不影响现有功能。
|
||||
|
||||
## Open Questions
|
||||
|
||||
无 - 所有设计决策已明确。
|
||||
@@ -0,0 +1,34 @@
|
||||
## Why
|
||||
|
||||
当前项目仅包含SMA双均线交叉策略(`strategies/sma_strategy.py`),需要引入基于MACD的趋势跟踪策略。MACD作为经典动量指标,结合EMA200趋势过滤,在A股市场表现优异,能更准确地捕捉趋势启动点和反转信号。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 创建 `strategies/macd_strategy.py` - 新增MACD趋势跟踪策略文件
|
||||
- 实现MACD指标计算 - 使用ta-lib库计算MACD(10,20,9)指标和EMA200趋势线
|
||||
- 实现策略交易逻辑 - MACD金叉/死叉信号 + EMA200趋势确认
|
||||
- 保持策略文件独立性 - 按照现有`strategy.py`模式实现(calculate_indicators、get_strategy、Strategy类)
|
||||
- 创建strategies目录 - 用于统一管理所有策略脚本
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `macd-trading`: MACD趋势跟踪策略,包含MACD指标计算、EMA200趋势过滤、以及基于金叉/死叉的交易信号生成
|
||||
|
||||
### Modified Capabilities
|
||||
无
|
||||
|
||||
## Impact
|
||||
|
||||
**依赖变化**:
|
||||
- ta-lib已手动安装(用于技术指标计算)
|
||||
|
||||
**代码影响**:
|
||||
- 不需要修改现有代码(`backtest.py`无需改动,策略文件模式保持一致)
|
||||
- 策略目录扩展至2个策略文件
|
||||
- 可通过`--strategy-file`参数切换使用SMA或MACD策略
|
||||
|
||||
**系统影响**:
|
||||
- 回测框架保持不变
|
||||
- 现有SMA策略完全不受影响
|
||||
- 可通过backtest.py的标准接口加载MACD策略
|
||||
@@ -0,0 +1,134 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: MACD趋势跟踪策略
|
||||
|
||||
系统应提供基于MACD指标的趋势跟踪交易策略,包括MACD计算、EMA200趋势过滤、以及基于金叉/死叉的交易信号生成。
|
||||
|
||||
#### Scenario: 策略文件加载
|
||||
|
||||
- **WHEN** 用户在命令行指定`--strategy-file strategies/macd_strategy.py`
|
||||
- **THEN** backtest.py成功加载策略文件并执行回测
|
||||
- **AND** 策略类正确注册所有技术指标到backtesting框架
|
||||
- **AND** 策略逻辑根据MACD金叉/死叉和EMA200位置生成交易信号
|
||||
|
||||
#### Scenario: MACD指标计算
|
||||
|
||||
- **WHEN** 调用`calculate_indicators(data)`函数,传入包含[Open, High, Low, Close, Volume, factor]的DataFrame
|
||||
- **THEN** 函数使用ta-lib计算以下指标并添加到DataFrame:
|
||||
- MACD线(DIF): 10日EMA - 20日EMA
|
||||
- MACD信号线(DEA): 9日EMA的MACD
|
||||
- MACD柱状图(Histogram): MACD线 - 信号线
|
||||
- EMA200: 200日指数移动平均线
|
||||
- **AND** 返回包含原始数据和所有新增指标的DataFrame
|
||||
- **AND** 指标名称使用ta-lib返回的默认列名(macd、macdsignal、macdhist)
|
||||
|
||||
#### Scenario: 策略初始化
|
||||
|
||||
- **WHEN** backtesting框架初始化MacdTrendStrategy策略类
|
||||
- **THEN** 调用`init()`方法
|
||||
- **AND** 在`init()`中通过`self.I()`注册以下指标到backtesting框架:
|
||||
- MACD线(`self.data.MACD_10_20_9`)
|
||||
- MACD信号线(`self.data.MACDs_10_20_9`)
|
||||
- EMA200(`self.data.EMA_200`)
|
||||
- **AND** 所有参数(fast_period=10、slow_period=20、signal_period=9)在策略类中定义为类变量
|
||||
- **AND** 注册的指标可直接在`next()`方法中访问
|
||||
|
||||
#### Scenario: MACD金叉买入信号
|
||||
|
||||
- **WHEN** 策略检测到MACD线上穿信号线(金叉)
|
||||
- **AND** 当前价格高于EMA200趋势线(确认上升趋势)
|
||||
- **AND** 当前无持仓或持仓方向与买入信号相反
|
||||
- **THEN** 策略平掉现有仓位(如有)
|
||||
- **AND** 策略开多仓(`self.buy()`)
|
||||
- **AND** 在趋势市场下捕捉上涨机会
|
||||
|
||||
#### Scenario: EMA200跌破卖出信号
|
||||
|
||||
- **WHEN** 策略检测到当前价格跌破EMA200趋势线
|
||||
- **AND** 当前持有多仓
|
||||
- **THEN** 策略平掉多仓(`self.position.close()`)
|
||||
- **AND** 不开空仓(仅平仓,避免逆势交易)
|
||||
- **AND** 在趋势转向时及时止损保护利润
|
||||
|
||||
#### Scenario: MACD死叉卖出信号
|
||||
|
||||
- **WHEN** 策略检测到MACD线下穿信号线(死叉)
|
||||
- **AND** 当前持有多仓
|
||||
- **THEN** 策略平掉多仓(`self.position.close()`)
|
||||
- **AND** 不开空仓
|
||||
- **AND** 在动量减弱时退出持仓
|
||||
|
||||
#### Scenario: EMA200下方不开仓
|
||||
|
||||
- **WHEN** 当前价格低于EMA200趋势线
|
||||
- **AND** 检测到MACD金叉信号
|
||||
- **THEN** 策略不执行买入操作
|
||||
- **AND** 避免在下跌趋势中逆势交易
|
||||
- **AND** 等待价格回到EMA200上方再考虑入场
|
||||
|
||||
#### Scenario: 空仓状态处理
|
||||
|
||||
- **WHEN** 策略当前无持仓
|
||||
- **AND** 检测到卖出信号(MACD死叉或EMA200跌破)
|
||||
- **THEN** 策略跳过卖出信号
|
||||
- **AND** 避免重复平仓导致错误
|
||||
|
||||
#### Scenario: 震荡市场过滤
|
||||
|
||||
- **WHEN** 市场处于震荡状态(价格围绕EMA200波动)
|
||||
- **AND** MACD产生频繁的假金叉/死叉信号
|
||||
- **THEN** EMA200趋势过滤减少交易频率
|
||||
- **AND** 避免在无明确趋势时频繁交易
|
||||
- **AND** 等待趋势明确后再入场
|
||||
|
||||
#### Scenario: 趋势市场顺势交易
|
||||
|
||||
- **WHEN** 市场处于明确上升趋势(价格持续在EMA200上方)
|
||||
- **AND** MACD金叉确认动量增强
|
||||
- **THEN** 策略及时入场捕捉上涨机会
|
||||
- **AND** 顺势交易提高胜率
|
||||
- **AND** EMA200确保不在下跌趋势中买入
|
||||
|
||||
#### Scenario: 参数配置
|
||||
|
||||
- **WHEN** 用户查看策略代码
|
||||
- **THEN** 策略参数清晰定义为类变量:
|
||||
- `fast_period = 10`(MACD快线周期)
|
||||
- `slow_period = 20`(MACD慢线周期)
|
||||
- `signal_period = 9`(MACD信号线周期)
|
||||
- **AND** 参数无需通过命令行传递
|
||||
- **AND** 参数可直接在代码中修改以适配不同市场环境
|
||||
|
||||
#### Scenario: 依赖管理
|
||||
|
||||
- **WHEN** 安装项目依赖
|
||||
- **THEN** ta-lib库已被正确安装(手动安装)
|
||||
- **AND** `uv run python -c "import talib"`成功执行
|
||||
- **AND** 策略文件可正常运行
|
||||
- **AND** 如ta-lib未安装,给出明确错误提示
|
||||
|
||||
#### Scenario: 回测兼容性
|
||||
|
||||
- **WHEN** 使用现有backtest.py框架
|
||||
- **THEN** 框架通过`load_strategy()`函数成功加载macd_strategy.py
|
||||
- **AND** 调用`calculate_indicators()`预处理数据
|
||||
- **AND** 初始化策略类并执行回测
|
||||
- **AND** 回测流程与SMA策略完全一致
|
||||
|
||||
#### Scenario: 指标数据完整性
|
||||
|
||||
- **WHEN** backtesting调用`calculate_indicators(data)`
|
||||
- **THEN** 返回的DataFrame包含所有必需列:
|
||||
- 原始列:[Open, High, Low, Close, Volume, factor]
|
||||
- MACD指标列:[MACD_10_20_9, MACDh_10_20_9, MACDs_10_20_9]
|
||||
- EMA趋势线列:[EMA_200]
|
||||
- **AND** 无NaN值(除预热期外)
|
||||
- **AND** 指标数据可用于策略决策和图表展示
|
||||
|
||||
#### Scenario: 预热期处理
|
||||
|
||||
- **WHEN** 数据长度不足以计算完整指标(前200天)
|
||||
- **THEN** 指标值为NaN
|
||||
- **AND** backtesting框架会自动跳过预热期
|
||||
- **AND** 策略逻辑在有足够数据后才执行
|
||||
- **AND** 避免因数据不足导致的错误信号
|
||||
@@ -0,0 +1,81 @@
|
||||
## 1. 环境准备
|
||||
|
||||
- [x] 1.1 安装ta-lib依赖包(已完成手动安装)
|
||||
- [x] 1.2 验证ta-lib安装成功(`uv run python -c "import talib"`无报错)
|
||||
|
||||
## 2. 目录结构
|
||||
|
||||
- [x] 2.1 确认strategies目录存在(如不存在则创建)
|
||||
- [x] 2.2 移动现有strategy.py到strategies/sma_strategy.py
|
||||
- [x] 2.3 验证文件移动成功且可正常导入
|
||||
|
||||
## 3. MACD策略文件创建
|
||||
|
||||
- [x] 3.1 创建strategies/macd_strategy.py文件
|
||||
- [x] 3.2 添加文件头部文档(策略说明、作者、日期)
|
||||
- [x] 3.3 添加必要的导入语句(pandas、backtesting、talib、crossover)
|
||||
- [x] 3.4 定义calculate_indicators()函数签名
|
||||
- [x] 3.5 定义get_strategy()函数
|
||||
- [x] 3.6 定义MacdTrendStrategy类框架
|
||||
|
||||
## 4. 指标计算实现
|
||||
|
||||
- [x] 4.1 在calculate_indicators()中使用ta-lib计算MACD指标
|
||||
- [x] 4.1.1 调用`talib.MACD(data['Close'], fastperiod=10, slowperiod=20, signalperiod=9)`
|
||||
- [x] 4.1.2 验证MACD返回3列(MACD线、信号线、柱状图)
|
||||
- [x] 4.1.3 计算EMA200趋势线(`talib.EMA(data['Close'], timeperiod=200)`)
|
||||
- [x] 4.1.4 返回包含所有指标的完整DataFrame
|
||||
|
||||
## 5. 策略类实现
|
||||
|
||||
- [x] 5.1 在MacdTrendStrategy类中定义可配置参数
|
||||
- [x] 5.1.1 fast_period = 10
|
||||
- [x] 5.1.2 slow_period = 20
|
||||
- [x] 5.1.3 signal_period = 9
|
||||
- [x] 5.2 实现init()方法
|
||||
- [x] 5.2.1 使用self.I()注册MACD线(self.data.MACD_10_20_9)
|
||||
- [x] 5.2.2 使用self.I()注册MACD信号线(self.data.MACDs_10_20_9)
|
||||
- [x] 5.2.3 使用self.I()注册EMA200(self.data.EMA_200)
|
||||
- [x] 5.2.4 验证所有指标正确注册
|
||||
- [x] 5.3 实现next()方法交易逻辑
|
||||
- [x] 5.3.1 导入crossover函数用于检测金叉/死叉
|
||||
- [x] 5.3.2 实现买入条件:crossover(MACD, Signal) AND Close > EMA200
|
||||
- [x] 5.3.3 实现卖出条件:crossover(Signal, MACD) OR Close < EMA200
|
||||
- [x] 5.3.4 处理空仓状态(避免重复平仓)
|
||||
- [x] 5.3.5 确保开仓前先平掉现有仓位
|
||||
|
||||
## 6. 代码验证
|
||||
|
||||
- [x] 6.1 检查Python语法正确性(无语法错误)
|
||||
- [x] 6.2 验证导入语句正确(所有依赖正确导入)
|
||||
- [x] 6.3 检查类继承自Strategy
|
||||
- [x] 6.4 检查策略文件结构符合SMA策略模式
|
||||
|
||||
## 7. 回测兼容性验证
|
||||
|
||||
- [x] 7.1 使用backtest.py加载macd_strategy.py(`uv run python backtest.py --strategy-file strategies/macd_strategy.py`)
|
||||
- [x] 7.2 验证策略文件成功加载无报错
|
||||
- [x] 7.3 执行简单回测(如测试股票、测试日期范围)
|
||||
- [x] 7.4 验证回测结果输出正常
|
||||
|
||||
## 8. 文档和注释
|
||||
|
||||
- [x] 8.1 在文件头部添加清晰的策略说明文档
|
||||
- [x] 8.2 在关键逻辑处添加代码注释
|
||||
- [x] 8.3 说明MACD参数选择理由(10-20-9组合)
|
||||
- [x] 8.4 说明EMA200趋势过滤原理
|
||||
- [x] 8.5 说明买入/卖出信号条件
|
||||
|
||||
## 9. 可选验证任务
|
||||
|
||||
- [ ] 9.1 对比MACD策略与SMA策略的回测结果
|
||||
- [ ] 9.2 测试不同参数组合的性能(如8-17-7、12-26-9)
|
||||
- [ ] 9.3 验证EMA200过滤对回撤的影响
|
||||
- [ ] 9.4 测试不同市场环境(牛市、熊市、震荡市)下的表现
|
||||
|
||||
## 10. 完成
|
||||
|
||||
- [x] 10.1 所有核心功能实现完成
|
||||
- [x] 10.2 代码质量符合Python最佳实践
|
||||
- [x] 10.3 策略可被backtest.py正常加载和执行
|
||||
- [x] 10.4 回测结果符合预期(策略逻辑正确执行)
|
||||
Reference in New Issue
Block a user