社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

用 Python 打造智能交易系统:MACD、ADX 和 SMA 三指标策略实战

数据科学实战 • 2 月前 • 106 次点击  


欢迎加入专注于财经数据与量化投研的【数据科学实战】知识星球!在这里,您将获取持续更新的《财经数据宝典》和《量化投研宝典》,这两部宝典相辅相成,为您在量化投研道路上提供明确指引。 《量化投研宝典》精选了业内持续维护且实用性强的开源工具(Backtrader、Qlib、VeighNa等),配合详细教程与代码示例,帮助您快速构建量化策略;《财经数据宝典》则汇集了多年财经数据维护经验,全面介绍从 AKShare、Tushare 到 Wind、iFind 等国内外数据源,并附有丰富的使用技巧。 无论您是量化投资新手还是经验丰富的研究者,星球社区都能帮您少走弯路,事半功倍,共同探索数据驱动的投资世界!

引言

在量化交易领域,如何构建一个既稳定又能适应市场变化的交易系统一直是投资者关注的焦点。今天,我们将深入探讨一个基于 MACD、ADX 和 SMA 三个经典技术指标的自适应交易策略。这个策略不仅实现了 612% 的回报率,更重要的是将最大回撤从 88% 降低到了 32%,展现出了优秀的风险控制能力。

本文将通过 Python 代码实现,带你一步步构建这个交易系统,并通过前向优化(Walk-Forward Optimization)和蒙特卡洛模拟等方法验证其稳健性。

核心指标介绍

1. MACD(移动平均收敛发散指标)

MACD 是一个动量振荡器,通过计算两条指数移动平均线的差值来判断趋势方向和潜在的反转点。

2. ADX(平均趋向指标)

ADX 用于衡量趋势的强度。通常当 ADX 值大于 20 时,表示市场处于强趋势中,这有助于过滤掉噪音信号。

3. SMA(简单移动平均线)

SMA 作为动态支撑/阻力线使用。价格突破 SMA 确认上升趋势,作为入场的最终确认信号。

策略逻辑

入场信号

同时满足以下条件时产生买入信号:

  • MACD 线上穿信号线
  • MACD 值大于零(确认多头动量)
  • ADX 大于 20(确保趋势强度)
  • 价格高于 SMA(确认趋势方向)

出场信号

满足以下条件时平仓:

  • MACD 线下穿信号线
  • MACD 值小于零
  • 价格低于 SMA

核心代码实现

指标计算函数

import numpy as np
import pandas as pd
import yfinance as yf
import vectorbt as vbt
import itertools

def calculate_indicators(df, macd_fast, macd_slow, macd_signal, adx_window, sma_window):
    """
    计算 MACD、ADX 和 SMA 指标
    
    参数:
    df: 包含价格数据的 DataFrame
    macd_fast: MACD 快线周期
    macd_slow: MACD 慢线周期
    macd_signal: MACD 信号线周期
    adx_window: ADX 计算窗口
    sma_window: SMA 计算窗口
    """

    df = df.copy()
    
    # 计算 MACD
    ema_fast = df['Close'].ewm(span=macd_fast, adjust=False).mean()
    ema_slow = df['Close'].ewm(span=macd_slow, adjust=False).mean()
    df['MACD'] = ema_fast - ema_slow
    df['MACD_Signal'] = df['MACD'].ewm(span=macd_signal, adjust=False).mean()
    
    # 计算 ADX
    high = df['High']
    low = df['Low']
    close = df['Close']
    
    # 计算方向性移动
    plus_dm = high.diff()
    minus_dm = low.diff()
    plus_dm[plus_dm 0] = 0
    minus_dm[minus_dm > 0] = 0
    
    # 计算真实波动范围
    tr1 = high - low
    tr2 = abs(high - close.shift())
    tr3 = abs(low - close.shift())
    tr = pd.concat([tr1, tr2, tr3], axis=1).max(axis=1)
    
    # 计算平均真实波动范围
    atr = tr.rolling(window=adx_window).mean()
    
    # 计算方向性指标
    plus_di = 100 * (plus_dm.rolling(window=adx_window).mean() / atr)
    minus_di = 100 * (minus_dm.rolling(window=adx_window).mean() / atr)
    
    # 计算 ADX
    dx = (abs(plus_di - minus_di) / (plus_di + minus_di)) * 100
    df['ADX'] = dx.rolling(window=adx_window).mean()
    
    # 计算 SMA
    df['SMA'] = df['Close'].rolling(window=sma_window).mean()
    
    return df

信号生成函数

def generate_signals(df):
    """
    根据策略逻辑生成买卖信号
    
    参数:
    df: 包含指标的 DataFrame
    
    返回:
    entry_signal: 买入信号
    exit_signal: 卖出信号
    """

    # 买入信号:MACD 上穿信号线且大于零,ADX > 20,价格 > SMA
    entry_signal = (
        (df['MACD'] > df['MACD_Signal']) &
        (df['MACD'].shift(1) <= df['MACD_Signal'].shift(1)) &
        (df['MACD'] > 0) &
        (df['ADX'] > 20) &
        (df['Close'] > df['SMA'])
    )
    
    # 卖出信号:MACD 下穿信号线且小于零,价格 < SMA
    exit_signal = (
        (df['MACD'] < df['MACD_Signal']) &
        (df['MACD'].shift(1) >= df['MACD_Signal'].shift(1)) &
        (df['MACD'] 0) &
        (df['Close'] < df['SMA'])
    )
    
    return entry_signal, exit_signal

前向优化(Walk-Forward Optimization)

前向优化是一种更接近实际交易的参数优化方法。它将数据分为训练集和测试集,每年使用前 4 年的数据找出最优参数,然后在下一年应用这些参数进行测试。

参数优化范围

  • MACD 快线:8 到 12
  • MACD 慢线:20 到 26
  • MACD 信号线:7 到 10
  • ADX 窗口:10 到 20
  • SMA 窗口:5 到 48(步长为 2)

前向优化实现

def walk_forward_optimization(df, start_year, end_year):
    """
    执行前向优化
    
    参数:
    df: 价格数据
    start_year: 开始年份
    end_year: 结束年份
    """

    results = []
    param_combinations = generate_parameter_combinations()
    
    # 对每一年进行优化
    for test_year in range(start_year + 4, end_year + 1):
        train_start = test_year - 4
        train_end = test_year - 1
        
        # 获取训练数据
        train_data = df[(df.index.year >= train_start) & 
                       (df.index.year <= train_end)]
        
        best_params = None
        best_performance = -np.inf
        
        # 测试所有参数组合
        for params in param_combinations:
            macd_f, macd_s, macd_sig, adx_w, sma_w = params
            
            # 计算指标和信号
            data = calculate_indicators(train_data, macd_f, macd_s, 
                                      macd_sig, adx_w, sma_w)
            entries, exits = generate_signals(data)
            
            # 创建投资组合并计算收益
            portfolio = vbt.Portfolio.from_signals(
                close=data['Open'],
                entries=entries.shift(1).fillna(False),
                exits=exits.shift(1).fillna(False),
                init_cash=100_000,
                fees=0.001,  # 0.1% 手续费
                slippage=0.002,  # 0.2% 滑点
                freq='D'
            )
            
            performance = portfolio.total_return()
            
            # 更新最佳参数
            if performance > best_performance:
                best_performance = performance
                best_params = params
        
        results.append({
            'Year': test_year,
            'Best_Params': best_params
        })
    
    return pd.DataFrame(results)

策略表现分析

优化结果

通过前向优化,我们得到了每年的最优参数组合:

  • 2020 年:MACD(8,23,7),ADX(12),SMA(5)
  • 2021 年:MACD(12,26,9),ADX(14),SMA(5)
  • 2022 年:MACD(12,26,9),ADX(16),SMA(5)
  • 2023 年:MACD(12,26,9),ADX(16),SMA(33)
  • 2024 年:MACD(10,25,7),ADX(16),SMA(5)
  • 2025 年:MACD(8,24,9),ADX(12),SMA(5)

关键绩效指标

策略在 2020-2025 年的表现:

  • 总收益率:612%(买入持有:391%)
  • 最大回撤:32%(买入持有:88%)
  • 夏普比率:1.59(买入持有:1.01)
  • 市场暴露时间:42.86%

Alpha 和 Beta 分析

# 计算策略相对于基准的 Alpha 和 Beta
from scipy.stats import linregress

def calculate_alpha_beta(portfolio_returns, benchmark_returns):
    """
    计算策略的 Alpha 和 Beta
    """

    # 使用线性回归计算
    slope, intercept, r_value, _, _ = linregress(
        benchmark_returns, portfolio_returns
    )
    
    beta = slope
    alpha = intercept
    correlation = portfolio_returns.corr(benchmark_returns)
    
    return alpha, beta, correlation

计算结果:

  • Alpha:0.0010(日度),约等于年化 25%
  • Beta:0.4369(策略波动性约为市场的 44%)
  • 相关系数:0.6607(与市场中度相关)

蒙特卡洛模拟验证

为了验证策略的稳健性,我们使用区块自助法(Block Bootstrap)进行蒙特卡洛模拟:

def monte_carlo_simulation(returns, n_simulations=1000, block_size=5):
    """
    使用区块自助法进行蒙特卡洛模拟
    
    参数:
    returns: 历史收益率
    n_simulations: 模拟次数
    block_size: 区块大小
    """

    n_days = len(returns)
    n_blocks = int(np.ceil(n_days / block_size))
    
    results = {
        'final_returns': [],
        'max_drawdowns': [],
        'sharpe_ratios': []
    }
    
    for _ in range(n_simulations):
        # 随机抽取区块
        block_indices = np.random.randint(
            0, len(returns) - block_size + 1, size=n_blocks
        )
        
        # 构建模拟收益序列
        sampled_returns = np.concatenate([
            returns[i:i+block_size] for i in block_indices
        ])[:n_days]
        
        # 计算累计收益
        equity = 100 * np.cumprod(1 + sampled_returns)
        
        # 计算绩效指标
        total_return = (equity[-1] / 100) - 1
        max_dd = np.max(1 - equity / np.maximum.accumulate(equity))
        sharpe = np.mean(sampled_returns) / np.std(sampled_returns) * np.sqrt(252)
        
        results['final_returns'].append(total_return)
        results['max_drawdowns'].append(max_dd)
        results['sharpe_ratios'].append(sharpe)
    
    return results

模拟结果

1000 次模拟的统计结果:

  • 平均最终收益:862.86%
  • 中位数收益:628.39%
  • 5% 分位数收益:104.35%
  • 95% 分位数收益:2425.87%
  • 平均最大回撤:37.68%
  • 平均夏普比率:1.21

重要发现:

  • 有 68.3% 的概率战胜买入持有策略
  • 100% 的模拟中最大回撤都小于买入持有

实战应用建议

  1. 参数自适应:建议每季度或半年重新优化参数,保持策略的适应性。

  2. 风险管理:虽然策略的回撤控制较好,但仍建议设置止损点,如单笔交易最大损失不超过 2%。

  3. 分散投资:将该策略应用于多个相关性较低的标的,进一步降低风险。

  4. 交易成本:实盘交易时要充分考虑手续费和滑点的影响,本策略已经考虑了 0.1% 的手续费和 0.2% 的滑点。

总结

本文介绍的基于 MACD、ADX 和 SMA 的自适应交易策略展现出了优秀的风险调整后收益。通过前向优化和严格的多条件信号筛选,策略不仅实现了较高的收益率,更重要的是大幅降低了最大回撤,提供了更平滑的收益曲线。

蒙特卡洛模拟结果表明,该策略具有较好的稳健性,在各种市场情况下都能保持相对稳定的表现。对于 Python 量化交易学习者来说,这是一个很好的实战案例,展示了如何将经典技术指标组合成一个完整的交易系统。

需要提醒的是,历史回测结果不代表未来表现,实际交易前请务必进行充分的测试和风险评估。

参考文章

加入专注于财经数据与量化投研的知识星球【数据科学实战】,获取完整研究解析、详细回测框架代码实现和完整策略逻辑实操指南。

财经数据与量化投研知识社区

核心权益如下:

  1. 赠送《财经数据宝典》完整文档,汇集多年财经数据维护经验
  2. 赠送《量化投研宝典》完整文档,汇集多年量化投研领域经验
  3. 赠送《PyBroker-入门及实战》视频课程,手把手学习量化策略开发
  4. 每日分享高质量量化投研文章、代码和相关资料
  5. 定期更新高频财经数据
  6. 参与年度不少于 10 次专属直播与录播课程
  7. 与核心开发者直接交流,解决实际问题
  8. 获取专业微信群交流机会和课程折扣

星球已有丰富内容积累,包括量化投研论文、财经高频数据、 PyBroker 视频教程、定期直播、数据分享和答疑解难。适合对量化投研和财经数据分析有兴趣的学习者及从业者。欢迎加入我们!

好文推荐

1. 用 Python 打造股票预测系统:Transformer 模型教程(一)

2. 用 Python 打造股票预测系统:Transformer 模型教程(二)

3. 用 Python 打造股票预测系统:Transformer 模型教程(三)

4. 用 Python 打造股票预测系统:Transformer 模型教程(完结)

5. 揭秘隐马尔可夫模型:因子投资的制胜武器

6. YOLO 也能预测股市涨跌?计算机视觉在股票市场预测中的应用

7. 金融 AI 助手:FinGPT 让你轻松掌握市场分析

8. 量化交易秘籍:为什么专业交易员都在用对数收益率?

9. Python 量化投资利器:Ridge、Lasso 和 Elastic Net 回归详解

10. 掌握金融波动率模型:完整 Python 实现指南

好书推荐

《Python编程:从入门到实践(第3版)》是一本广受欢迎的 Python 入门经典教材,由经验丰富的程序员 Eric Matthes 编写。该书采用循序渐进的教学方式,从基础语法讲解到实战项目开发,内容编排合理,实例丰富,语言通俗易懂。全书配有大量练习题和完整项目实战,包括数据可视化、网络爬虫、Web 应用开发等,让读者在实践中掌握编程技巧。第3版还增加了 f-string、海龟绘图等最新的 Python 特性内容。这本书不仅适合零基础读者入门学习,也非常适合想系统掌握 Python 的编程爱好者以及数据分析、人工智能等领域的学习者。它不仅教授编程知识,更注重培养读者的编程思维,是一本非常值得投资的 Python 学习指南。


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/184606
 
106 次点击