算法交易新突破:Python 优化 RSI 全攻略,轻松提升盈利能力!

作者:老余捞鱼

原创不易,转载请标明出处及原作者。

写在前面的话:在这篇文章里,我详细分享了如何用Python优化算法交易中的RSI指标。通过调整周期、超买/超卖阈值和止损百分比,显著提升了交易策略的表现。结合苹果股票数据的回测结果,效果一目了然!如果你也想提高交易绩效,这些实用技巧绝对不容错过,赶紧来学习吧!

一、优化 RSI 指标


1.1 什么是 RSI ?

RSI (Relative Strength Index)是一种动量震荡指标,用于测量价格变动的速度和变化。它在 0 和 100 之间震荡,通常在图表上显示为一条线,随着资产价格的变动而变动。

RSI 的计算公式为:RSI = 100 × RS / (1 + RS),其中RS = N天内收市价上涨数之和的平均值 / N天内收市价下跌数之和的平均值。

1.2 RSI 应用

RSI 是一种动量震荡指标,通过评估价格变动的速度和幅度,帮助判断市场的超买或超卖状态。当 RSI 低于 30 时,可能暗示着买入机会;而当 RSI 超过 70,则可能是卖出的信号。

  • 超买与超卖:通常,RSI值超过70被认为市场处于超买状态,可能面临回调或下跌压力;而RSI值低于30则被视为超卖状态,可能即将出现反弹或上涨。
  • 趋势判断:RSI值大于50通常表示市场处于多方市场(即上涨趋势),而小于50则表示市场处于空方市场(即下跌趋势)。
  • 交叉信号:短期RSI(如6日RSI)与长期RSI(如12日RSI)的交叉情况可以提供交易信号。当短期RSI从下向上突破长期RSI时,视为买入信号;反之,从上向下突破时,则为卖出信号。
  • 背离现象:当资产价格继续上涨而RSI不再创新高,或价格继续下跌而RSI不再创新低时,这种背离现象可能预示着市场趋势的即将逆转。

1.3 优化RSI

如果运用得当,RSI 指标能够通过精准识别买卖点,显著提升算法交易策略的盈利能力。然而,默认参数(比如常见的 14 天周期)并不适合所有市场或资产,优化调整才能发挥最大效果。优化 RSI 涉及调整其参数,比如周期和超买/超卖阈值,以提高策略性能。

  • RSI 周期:调整周期长度会极大地影响指标对价格变动的反应能力。周期越短可能越敏感,产生的信号越多,但噪音也越大。周期越长,信号越平滑,但可能会错过市场方向的快速变化。
  • 超买/超卖阈值:标准的超买/超卖水平是 70 和 30,但通过历史数据优化这些阈值,可以更精准地捕捉市场状态。

如果你能深入理解这两个指标,并掌握优化它们性能的方法,就能灵活运用 RSI,实现交易利润的最大化!

二、Python 优化 RSI


2.1 计算 RSI

下图为苹果(AAPL)股票价格与 RSI 的对比图。

我们可用使用下面的 Python 代码实现,并根据需要调整时间段。

import yfinance as yf
import pandas as pd
import matplotlib.pyplot as plt

def calculate_rsi(data, period=14):
    """
    Calculate the Relative Strength Index (RSI).
    :param data: DataFrame with 'Close' column containing closing prices.
    :param period: Period for calculating RSI, default is 14.
    :return: DataFrame with RSI values.
    """
    delta = data['Close'].diff(1)
    gain = delta.where(delta > 0, 0)
    loss = -delta.where(delta < 0, 0)

    avg_gain = gain.rolling(window=period).mean()
    avg_loss = loss.rolling(window=period).mean()

    rs = avg_gain / avg_loss
    rsi = 100 - (100 / (1 + rs))
    data['RSI'] = rsi

    return data

def plot_rsi(data, ticker):
    """
    Plot closing prices and RSI.
    :param data: DataFrame with 'Close' and 'RSI' columns.
    :param ticker: Stock ticker symbol for the title.
    """
    fig, axes = plt.subplots(2, figsize=(12, 8), sharex=True)

    # Plot closing price
    axes[0].plot(data.index, data['Close'], label='Close Price')
    axes[0].set_title(f'{ticker} Closing Prices')
    axes[0].set_ylabel('Price')
    axes[0].legend()

    # Plot RSI
    axes[1].plot(data.index, data['RSI'], label='RSI', color='orange')
    axes[1].axhline(70, color='red', linestyle='--', label='Overbought (70)')
    axes[1].axhline(30, color='green', linestyle='--', label='Oversold (30)')
    axes[1].set_title(f'{ticker} RSI')
    axes[1].set_ylabel('RSI')
    axes[1].set_xlabel('Date')
    axes[1].legend()

    plt.tight_layout()
    plt.show()

# Fetch stock data
ticker = "AAPL"  # Replace with your preferred stock ticker
data = yf.download(ticker, start="2014-01-01", end="2024-01-01")
data_clean = data.copy()
data_clean = data_clean.ffill()
data_clean.columns = ['Adj Close','Close','High','Low','Open','Volume']
data = data_clean.copy()

# Calculate RSI
data = calculate_rsi(data)

# Plot RSI
plot_rsi(data, ticker)

calculate_rsi 函数会根据指定时间段(默认 14 天)的股票收盘价计算 RSI 值。它通过比较平均涨幅和平均跌幅的比例,生成一个 0 到 100 之间的震荡指标,帮助判断市场状态。

2.2 回测 RSI 交易策略

计算出 RSI 值后,我们可以通过回溯测试模拟策略的历史表现。具体规则是:当 RSI 从下方突破超卖水平(通常为 30)时买入,当 RSI 从上方跌破超买水平(通常为 70)时卖出。

def backtest_rsi(data, rsi_period=14, overbought=70, oversold=30, stop_loss_pct=0.05, initial_balance=10000):
    data = calculate_rsi(data, period=rsi_period)
    balance = initial_balance
    position = 0
    entry_price = 0

    for i in range(1, len(data)):
        row = data.iloc[i]
        prev_row = data.iloc[i - 1]

        # Buy signal: RSI crosses above the oversold level
        if position == 0 and prev_row['RSI'] < oversold and row['RSI'] >= oversold:
            position = balance / row['Close']
            entry_price = row['Close']
            balance = 0

        # Sell signal: RSI crosses below the overbought level or stop-loss triggered
        elif position > 0:
            stop_loss_price = entry_price * (1 - stop_loss_pct)
            if (row['RSI'] <= overbought and prev_row['RSI'] > overbought) or row['Close'] <= stop_loss_price:
                balance = position * row['Close']
                position = 0

    if position > 0:
        balance += position * data.iloc[-1]['Close']

    return balance

在这个功能中,我们将使用历史股票数据进行回溯测试。模拟策略从初始资金(例如 10,000 美元)开始,根据 RSI 信号执行买卖操作。为了有效管理风险,我们还加入了止损功能:当价格跌破入场价的指定百分比时,自动卖出,避免进一步亏损。

根据默认参数(RSI 周期=14、超买水平=70、超卖水平=30)的回测结果,初始资金从 10,000 美元仅增长到 10,167 美元,表现平平,甚至不如简单的“买入并持有”策略。显然,我们需要优化参数,找到更佳的组合来提升策略效果。

2.3 优化 RSI 参数

下一步是找到 RSI 关键参数的最佳值,如 RSI 周期、超买和超卖水平,以及止损百分比。我们通过一个优化函数来探索这些参数的各种组合,从而实现这一目标:

from itertools import product

def optimize_rsi(data, rsi_periods, overbought_levels, oversold_levels, stop_loss_pcts):
    results = []
    for rsi_period, overbought, oversold, stop_loss_pct in product(rsi_periods, overbought_levels, oversold_levels, stop_loss_pcts):
        if overbought <= oversold:
            continue  # Skip invalid combinations

        final_balance = backtest_rsi(data, rsi_period, overbought, oversold, stop_loss_pct)
        results.append({
            'RSI Period': rsi_period,
            'Overbought Level': overbought,
            'Oversold Level': oversold,
            'Stop Loss %': stop_loss_pct,
            'Final Balance': final_balance
        })

    results_df = pd.DataFrame(results)
    return results_df

# Optimize RSI parameters
rsi_periods = range(5, 21, 1)  # RSI periods from 5 to 20
overbought_levels = range(65, 86, 5)  # Overbought levels from 65 to 85
oversold_levels = range(15, 36, 5)  # Oversold levels from 15 to 35
stop_loss_pcts = [0.02, 0.05, 0.1]  # Stop-loss percentages

results_df = optimize_rsi(data, rsi_periods, overbought_levels, oversold_levels, stop_loss_pcts)

# Find the best parameters
best_params = results_df.loc[results_df['Final Balance'].idxmax()]
print("Best Parameters:")
print(best_params)

# Plot optimization results
plot_optimization_results(results_df)

我们利用 itertools.product 函数遍历所有可能的参数组合。针对每一种组合,都会运行一次回溯测试,并将最终的账户余额记录在 DataFrame 中,方便后续分析和比较。

2.4 优化结果可视化

优化参数后,我们需要将结果可视化,以便快速找到最佳组合。比如,可以通过创建热图来直观展示不同参数设置下的最终账户余额变化,帮助我们锁定最有利的策略配置。

def plot_optimization_results(results_df):
    pivot = results_df.pivot_table(
        index='RSI Period',
        columns='Overbought Level',
        values='Final Balance',
        aggfunc='max'
    )

    plt.figure(figsize=(10, 8))
    plt.title("Optimization Results: Final Balance")
    sns.heatmap(pivot, annot=True, fmt=".2f", cmap="viridis")
    plt.xlabel("Overbought Level")
    plt.ylabel("RSI Period")
    plt.show()

最佳建议参数

  • RSI 周期:12
  • 超买水平:85
  • 超卖水平:35
  • 止损 % : 0.1
  • 最终余额 : 59341.05

这张热图展示了最终账户余额如何随 RSI 周期和超买水平的不同组合而变化。但由于只有两个维度,超卖水平这一关键参数未能充分体现。为了更好地分析,我们将切换到三维图,全面展示参数之间的关系。

2.5 增强可视化的 3D 绘图

如果需要更详细的分析,可以使用三维散点图,将最终账户余额与 RSI 周期、超买水平和超卖水平进行对比,从而更全面地评估参数组合的效果。

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt

def plot_3d_optimization_results(results_df):
    """
    Plot the optimization results in 3D.
    """
    fig = plt.figure(figsize=(12, 8))
    ax = fig.add_subplot(111, projection='3d')

    # Extract data for the plot
    rsi_period = results_df['RSI Period']
    overbought = results_df['Overbought Level']
    oversold = results_df['Oversold Level']
    final_balance = results_df['Final Balance']

    # Create a scatter plot
    scatter = ax.scatter(rsi_period, overbought, oversold, c=final_balance, cmap='viridis', alpha=0.8)

    # Add labels and title
    ax.set_title('3D Optimization Results: Final Balance', pad=20)
    ax.set_xlabel('RSI Period', labelpad=10)
    ax.set_ylabel('Overbought Level', labelpad=10)
    ax.set_zlabel('Oversold Level', labelpad=10)

    # Add color bar for balance
    cbar = fig.colorbar(scatter, ax=ax, shrink=0.6, aspect=10)
    cbar.set_label('Final Balance')

    plt.show()

# Plot the 3D optimization results
plot_3d_optimization_results(results_df)

这种三维图可以更详细地显示参数之间的相互作用以及最终的平衡,帮助交易者做出数据驱动的决策。

我们可以使用之前编码的 backtest_rsi 函数查看更详细的回溯测试结果,如下图所示。

# Backtest with best parameters
_, _, best_equity_curve = backtest_rsi(
    data,
    rsi_period=12,
    overbought=85,
    oversold=35,
    stop_loss_pct=0.1
)

# Plot equity curve
plot_equity_curve(best_equity_curve)

从优化后的结果来看,初始资金从 10,000 美元增长到了 59,341.05 美元,且最大回撤控制在 25% 以内,表现相当出色。不过从实战出发,如果选择买入并持有 AAPL 股票 10 年,尽管波动风险更高,但收益可能更为可观。

三、观点总结

在构建交易系统时,有一个关键原则必须牢记:在将系统投入实际交易之前,一定要进行前向优化测试。只有这样,才能确保您的系统和参数在当前市场中依然有效,避免盲目部署带来的风险。

  • RSI 是衡量价格变动速度和变化的重要指标,对于识别交易机会至关重要。
  • 默认的 RSI 参数可能需要根据具体市场和资产进行调整,以提高策略的有效性。
  • 回溯测试是评估和优化交易策略的关键工具,可以帮助交易者了解历史表现并调整策略。
  • 优化 RSI 参数可以显著提高交易策略的盈利能力,尤其是通过调整 RSI 周期、超买/超卖阈值和止损机制。
  • 可视化优化结果有助于交易者做出更明智的决策,热图和三维散点图是两种有效的可视化方法。
  • 前向优化是确保交易系统在实际市场中有效性的重要步骤,应在实际交易之前进行。
  • 交易者应该持续学习和适应市场变化,以保持交易策略的相关性和盈利能力。

感谢您阅读到最后,希望这篇文章为您带来了新的启发和实用的知识!如果觉得有帮助,请不吝点赞和分享,您的支持是我持续创作的动力。祝您投资顺利,收益长虹!如果对文中内容有任何疑问,欢迎留言,我会尽快回复!


本文内容仅限技术探讨和学习,不构成任何投资建议。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老余捞鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值