社区所有版块导航
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 实现自适应均线 + 波动率交易策略,新手也能看懂

数据科学实战 • 9 月前 • 505 次点击  

欢迎加入专注于财经数据与量化投研的【数据科学实战】知识星球!在这里,您将获取持续更新的《财经数据宝典》和《量化投研宝典》,这两部宝典相辅相成,为您在量化投研道路上提供明确指引。 我们提供了精选的国内外量化投研的 180+ 篇高质量文章,并每日更新最新研究成果,涵盖策略开发、因子分析、风险管理等核心领域。 无论您是量化投资新手还是经验丰富的研究者,星球社区都能帮您少走弯路,事半功倍,共同探索数据驱动的投资世界!

引言

在量化交易中,如何在追踪趋势的同时控制风险,一直是交易者们关注的核心问题。今天给大家介绍一个结合了 Kaufman 自适应移动平均线(KAMA)和平均真实波幅(ATR)的交易策略。这个策略的核心思想是:用 KAMA 捕捉趋势,用 ATR 控制风险,再通过 Optuna 自动优化参数。

这篇文章将带你从零开始理解这个策略的原理和实现方法,即使你是 Python 新手,也能跟着代码一步步学习。

策略的核心思想

这个策略主要由三个部分组成:

KAMA 自适应趋势跟踪:不同于简单移动平均线(SMA)或指数移动平均线(EMA),KAMA 会根据市场波动自动调整平滑程度。在趋势明显时反应迅速,在震荡行情中则更加平滑,避免频繁交易。

ATR 波动率过滤:ATR 用来衡量价格波动的剧烈程度。当波动率过高时,策略会避免入场;如果持仓期间波动率突然飙升,则立即止损出场。

Optuna 参数优化:不用手动猜测最佳参数,让 Optuna 自动搜索最优的 KAMA 周期和 ATR 阈值组合。

代码实现

1. 获取历史数据

首先,我们需要获取股票的历史价格数据。这里使用 Financial Modeling Prep API:

import pandas as pd
import requests

def fetch_data_fmp(symbol: str, start_date: str, end_date: str, api_key: str):
    """
    从 Financial Modeling Prep API 获取历史价格数据
    
    参数:
        symbol: 股票代码,如 'TSLA'
        start_date: 开始日期,格式 'YYYY-MM-DD'
        end_date: 结束日期,格式 'YYYY-MM-DD'
        api_key: API 密钥
    
    返回:
        包含日期、开盘价、最高价、最低价、收盘价、成交量的 DataFrame
    """

    url = f"https://financialmodelingprep.com/api/v3/historical-price-full/{symbol}?from={start_date}&to={end_date}&apikey={api_key}"
    resp = requests.get(url)
    resp.raise_for_status()
    data = resp.json().get('historical', [])
    df = pd.DataFrame(data)
    df['date'] = pd.to_datetime(df['date'])
    df = df.sort_values('date').reset_index(drop=True)
    return df[['date''open''high''low''close''volume']]

2. 计算 KAMA 指标

KAMA 的核心是效率比率(ER)。当价格频繁变向时,ER 较低,KAMA 平滑程度更高;当价格趋势明显时,ER 较高,KAMA 更紧密跟随价格。

import numpy as np

def kaufman_adaptive_moving_average(df, er_period, fast_period, slow_period):
    """
    计算 Kaufman 自适应移动平均线
    
    参数:
        df: 包含收盘价的 DataFrame
        er_period: 效率比率计算周期
        fast_period: 快速平滑常数周期
        slow_period: 慢速平滑常数周期
    
    返回:
        添加了 KAMA 列的 DataFrame
    """

    close = df['close'].values
    
    # 计算价格变化幅度
    change = abs(close[er_period:] - close[:-er_period])
    
    # 计算波动性(价格变化的累加)
    volatility = np.sum(abs(close[1:] - close[:-1]).reshape(-1, er_period), axis=1)
    
    # 效率比率 = 价格变化 / 波动性
    er = change / volatility
    
    # 计算平滑常数
    sc_fast = 2 / (fast_period + 1)
    sc_slow = 2 / (slow_period + 1)
    sc = (er * (sc_fast - sc_slow) + sc_slow) ** 2
    
    # 计算 KAMA
    kama = np.zeros(len(close))
    kama[:er_period] = close[:er_period]
    for i in range(er_period, len(close)):
        kama[i] = kama[i-1] + sc[i-er_period] * (close[i] - kama[i-1])
    
    df['KAMA'] = kama
    return df

3. 计算 ATR 指标

ATR 用于衡量价格波动的幅度,是风险控制的关键指标:

def average_true_range(df, window=14):
    """
    计算平均真实波幅(ATR)
    
    参数:
        df: 包含最高价、最低价、收盘价的 DataFrame
        window: ATR 计算窗口,默认 14 天
    
    返回:
        添加了 ATR 列的 DataFrame
    """

    # 计算真实波幅的三个组成部分
    high_low = df['high'] - df['low']  # 当日最高价减最低价
    high_close = abs(df['high'] - df['close'].shift())  # 当日最高价减昨日收盘价
    low_close = abs(df['low'] - df['close'].shift())  # 当日最低价减昨日收盘价
    
    # 取三者中的最大值作为真实波幅
    tr = pd.concat([high_low, high_close, low_close], axis=1).max(axis=1)
    
    # 计算移动平均得到 ATR
    atr = tr.rolling(window).mean()
    df['ATR'] = atr
    return df

4. 生成交易信号

根据 KAMA 和 ATR 生成买卖信号:

def generate_signals(df, atr_min_pct, atr_max_pct, atr_exit_pct):
    """
    生成交易信号
    
    买入条件:价格在 KAMA 之上,且 ATR 百分比在合理范围内
    卖出条件:价格跌破 KAMA,或 ATR 百分比超过退出阈值
    
    参数:
        df: 包含 KAMA 和 ATR 的 DataFrame
        atr_min_pct: ATR 最小百分比阈值
        atr_max_pct: ATR 最大百分比阈值
        atr_exit_pct: ATR 退出百分比阈值
    
    返回:
        添加了持仓信号的 DataFrame
    """

    # 计算 ATR 占收盘价的百分比
    df['atr_pct'] = df['ATR'] / df['close'] * 100
    df['position'] = 0
    
    for i in range(1, len(df)):
        # 买入信号:价格高于 KAMA 且波动率在可接受范围内
         if df['close'][i] > df['KAMA'][i] and atr_min_pct <= df['atr_pct'][i] < atr_max_pct:
            df.at[i, 'position'] = 1
        # 卖出信号:价格低于 KAMA 或波动率过高
        elif df['close'][i] < df['KAMA'][i] or df['atr_pct'][i] > atr_exit_pct:
            df.at[i, 'position'] = 0
        else:
            # 保持前一天的持仓状态
            df.at[i, 'position'] = df.at[i-1'position']
    
    return df

5. 回测逻辑

模拟交易过程,计算最终收益:

def backtest(df, initial_balance=1000):
    """
    回测策略表现
    
    参数:
        df: 包含持仓信号的 DataFrame
        initial_balance: 初始资金,默认 1000
    
    返回:
        最终账户余额
    """

    balance = initial_balance  # 账户余额
    position = 0  # 持仓数量
    entry_price = 0  # 入场价格
    
    for i in range(len(df)):
        # 开仓:从无仓位变为有仓位
        if position == 0 and df['position'][i] == 1:
            position = balance / df['close'][i]  # 全仓买入
            entry_price = df['close'][i]
            balance = 0
        # 平仓:从有仓位变为无仓位
        elif position > 0 and df['position'][i] == 0:
            balance = position * df['close'][i]  # 卖出所有持仓
            position = 0
    
    # 如果最后还有持仓,按最后收盘价结算
    if position > 0:
        balance = position * df['close'].iloc[-1]
    
    return balance

6. 使用 Optuna 优化参数

让 Optuna 自动搜索最优参数组合:

import optuna

def objective(trial):
    """
    Optuna 优化目标函数
    
    自动搜索最优的策略参数组合
    """

    # 定义参数搜索范围
    er_period = trial.suggest_int('er_period'230)  # 效率比率周期
    fast_period = trial.suggest_int('fast_period'220)  # 快速周期
    slow_period = trial.suggest_int('slow_period'20100)  # 慢速周期
    atr_window = trial.suggest_int('atr_window'530)  # ATR 窗口
    atr_min_pct = trial.suggest_uniform('atr_min_pct'0.53)  # ATR 最小百分比
    atr_max_pct = trial.suggest_uniform('atr_max_pct'15)  # ATR 最大百分比
    atr_exit_pct = trial.suggest_uniform('atr_exit_pct'520)  # ATR 退出百分比
    
    # 复制数据并应用策略
    df_copy = df.copy()
    df_copy = kaufman_adaptive_moving_average(df_copy, er_period, fast_period, slow_period)
    df_copy = average_true_range(df_copy, atr_window)
    df_copy = generate_signals(df_copy, atr_min_pct, atr_max_pct, atr_exit_pct)
    
    # 返回最终收益作为优化目标
    final_balance = backtest(df_copy)
    return final_balance

# 创建优化研究并运行
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=100)

实战案例:TSLA 回测结果

以 TSLA(特斯拉)股票为例,使用 Sharpe 比率作为优化指标,策略表现如下:

指标
数值
策略总收益
5394.21%
买入持有收益
1290.93%
总交易次数
90 次
盈利交易比例
45.56%
Sharpe 比率
1.76
年化收益率(CAGR)
77.58%
最大回撤
-39.42%

从结果可以看出,策略收益远超买入持有策略,同时通过 ATR 过滤有效控制了波动率较高时期的风险。

总结

这个 KAMA + ATR 策略的优势在于:

KAMA 的自适应特性使其在趋势行情和震荡行情中都能保持较好的表现,避免了传统均线在震荡期频繁产生假信号的问题。ATR 过滤机制则在高波动时期暂停交易,有效降低了策略的回撤风险。Optuna 自动优化省去了手动调参的繁琐工作,提高了策略开发效率。

当然,需要注意的是,任何基于历史数据优化的策略都存在过拟合风险,实盘交易前务必进行充分的样本外测试。

参考文章

加入专注于财经数据与量化投研的知识星球【数据科学实战】,获取本文完整研究解析、代码实现细节。

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

核心权益如下:

  1. 赠送《财经数据宝典》完整文档,汇集多年财经数据维护经验
  2. 赠送《量化投研宝典》完整文档,汇集多年量化投研领域经验
  3. 赠送《PyBroker-入门及实战》视频课程,手把手学习量化策略开发
  4. 每日分享高质量量化投研文章(已更新 180+篇)、代码和相关资料
  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社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/189875