当前位置:首页>python>Python量化实战:用Pandas计算RSI相对强弱指标,识别超买超卖!

Python量化实战:用Pandas计算RSI相对强弱指标,识别超买超卖!

  • 2026-09-12 20:50:39
Python量化实战:用Pandas计算RSI相对强弱指标,识别超买超卖!

💡 导语:RSI是判断股票超买超卖的经典指标。今天教你用Python + Pandas轻松计算RSI,识别买卖时机,让量化分析变得简单高效!


一、RSI指标原理详解

1.1 什么是RSI?

RSI(Relative Strength Index,相对强弱指标) 由Welles Wilder于1978年提出,是衡量股票价格变动速度和变化幅度的动量指标。

1.2 RSI计算公式

RSI = 100 - (100 / (1 + RS))

其中:
RS = 平均上涨幅度 / 平均下跌幅度

计算步骤:
1. 计算价格变动(今日收盘价 - 昨日收盘价)
2. 区分上涨日和下跌日
3. 计算N日平均上涨幅度和平均下跌幅度
4. 代入公式计算RSI值

1.3 RSI的解读

       
                                           
RSI值状态信号
RSI > 80严重超买强烈卖出信号
RSI > 70超买区考虑卖出
50 < RSI < 70强势区持有观望
30 < RSI < 50弱势区关注机会
RSI < 30超卖区考虑买入
RSI < 20严重超卖强烈买入信号
       
     

⚠️ 注意:RSI在单边行情中可能长期停留在超买/超卖区,需结合其他指标使用。


二、Python实战:计算RSI指标

2.1 环境准备

pip install akshare pandas numpy matplotlib

2.2 完整代码

import akshare as ak
import
 pandas as pd
import
 numpy as np
import
 matplotlib.pyplot as plt
from
 datetime import datetime, timedelta

def
 calculate_rsi(data, period=14):
    """
    计算RSI指标
    
    Parameters:
        data: DataFrame,包含'收盘'列
        period: RSI计算周期,默认14日
    
    Returns:
        DataFrame,新增'RSI'列
    """

    df = data.copy()
    
    # 计算价格变动

    df['change'] = df['收盘'].diff()
    
    # 区分上涨和下跌

    df['gain'] = np.where(df['change'] > 0, df['change'], 0)
    df['loss'] = np.where(df['change'] < 0, -df['change'], 0)
    
    # 计算平均上涨和平均下跌(使用Wilder平滑法)

    df['avg_gain'] = df['gain'].ewm(alpha=1/period, min_periods=period).mean()
    df['avg_loss'] = df['loss'].ewm(alpha=1/period, min_periods=period).mean()
    
    # 计算RS和RSI

    df['rs'] = df['avg_gain'] / df['avg_loss']
    df['rsi'] = 100 - (100 / (1 + df['rs']))
    
    return
 df

# 获取股票数据

symbol = "600519"  # 贵州茅台
df = ak.stock_zh_a_hist(symbol=symbol, period="daily", 
                        start_date="20241001", end_date="20260325")

# 计算RSI

df = calculate_rsi(df, period=14)

# 查看结果

print
(df[['日期', '收盘', 'rsi']].tail(10))

输出示例:

           日期      收盘        rsi
280  2026-03-13  1560.00  42.345678
281  2026-03-14  1575.00  48.234567
...
289  2026-03-24  1520.00  28.456789  ← 超卖区!

三、识别超买超卖信号

3.1 信号识别代码

def identify_signals(df, overbought=70, oversold=30):
    """
    识别RSI超买超卖信号
    
    Parameters:
        df: 包含RSI的DataFrame
        overbought: 超买阈值,默认70
        oversold: 超卖阈值,默认30
    """

    signals = []
    
    for
 i in range(1, len(df)):
        # 超卖区反弹(买入信号)

        if
 df['rsi'].iloc[i-1] < oversold and df['rsi'].iloc[i] >= oversold:
            signals.append({
                'date'
: df['日期'].iloc[i],
                'price'
: df['收盘'].iloc[i],
                'rsi'
: df['rsi'].iloc[i],
                'signal'
: '买入',
                'reason'
: f'RSI从超卖区({df["rsi"].iloc[i-1]:.1f})反弹'
            })
        
        # 超买区回落(卖出信号)

        elif
 df['rsi'].iloc[i-1] > overbought and df['rsi'].iloc[i] <= overbought:
            signals.append({
                'date'
: df['日期'].iloc[i],
                'price'
: df['收盘'].iloc[i],
                'rsi'
: df['rsi'].iloc[i],
                'signal'
: '卖出',
                'reason'
: f'RSI从超买区({df["rsi"].iloc[i-1]:.1f})回落'
            })
    
    return
 pd.DataFrame(signals)

# 识别信号

signals_df = identify_signals(df)
print
(f"\n共识别到 {len(signals_df)} 个交易信号:")
print
(signals_df.to_string(index=False))

四、可视化展示

4.1 绘制RSI图表

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(14, 10), 
                                gridspec_kw={'height_ratios': [3, 1]})

# 绘制股价

ax1.plot(df['日期'], df['收盘'], label='收盘价', color='#0F4C81', linewidth=1.5)
ax1.set_title('贵州茅台(600519) 股价与RSI指标', fontsize=14, fontweight='bold')
ax1.set_ylabel('价格(元)')
ax1.legend()
ax1.grid(True, alpha=0.3)

# 标记买卖信号

for
 _, row in signals_df.iterrows():
    if
 row['signal'] == '买入':
        ax1.scatter(row['date'], row['price'], color='green', 
                   marker='^', s=100, zorder=5, label='买入' if _ == 0 else "")
    else
:
        ax1.scatter(row['date'], row['price'], color='red', 
                   marker='v', s=100, zorder=5, label='卖出' if _ == 0 else "")

# 绘制RSI

ax2.plot(df['日期'], df['rsi'], label='RSI(14)', color='purple', linewidth=1.5)
ax2.axhline(y=70, color='red', linestyle='--', alpha=0.7, label='超买线(70)')
ax2.axhline(y=30, color='green', linestyle='--', alpha=0.7, label='超卖线(30)')
ax2.axhline(y=50, color='gray', linestyle='-', alpha=0.3)
ax2.fill_between(df['日期'], 30, 70, alpha=0.1, color='gray')
ax2.set_ylabel('RSI')
ax2.set_xlabel('日期')
ax2.legend()
ax2.grid(True, alpha=0.3)
ax2.set_ylim(0, 100)

plt.tight_layout()
plt.show()

五、实战策略与回测思路

5.1 简单RSI策略

def rsi_strategy(df, overbought=70, oversold=30):
    """
    RSI简单交易策略
    - RSI < 30:买入
    - RSI > 70:卖出
    """

    position = 0  # 0:空仓, 1:持仓
    trades = []
    
    for
 i in range(len(df)):
        if
 df['rsi'].iloc[i] < oversold and position == 0:
            # 买入信号

            position = 1
            trades.append({
                'date'
: df['日期'].iloc[i],
                'action'
: '买入',
                'price'
: df['收盘'].iloc[i],
                'rsi'
: df['rsi'].iloc[i]
            })
        elif
 df['rsi'].iloc[i] > overbought and position == 1:
            # 卖出信号

            position = 0
            trades.append({
                'date'
: df['日期'].iloc[i],
                'action'
: '卖出',
                'price'
: df['收盘'].iloc[i],
                'rsi'
: df['rsi'].iloc[i]
            })
    
    return
 pd.DataFrame(trades)

# 执行策略

trades_df = rsi_strategy(df)
print
("交易记录:")
print
(trades_df.to_string(index=False))

# 计算收益

if
 len(trades_df) >= 2:
    total_return = 1
    for
 i in range(0, len(trades_df) - 1, 2):
        if
 trades_df.iloc[i]['action'] == '买入':
            buy_price = trades_df.iloc[i]['price']
            sell_price = trades_df.iloc[i + 1]['price']
            trade_return = sell_price / buy_price
            total_return *= trade_return
            print
(f"\n交易{i//2+1}: {buy_price:.2f} → {sell_price:.2f}, 收益率: {(trade_return-1)*100:.2f}%")
    
    print
(f"\n总收益率: {(total_return-1)*100:.2f}%")

六、RSI进阶技巧

6.1 RSI背离识别

def detect_divergence(df, window=20):
    """
    识别RSI背离
    - 顶背离:价格新高,RSI未新高(看跌)
    - 底背离:价格新低,RSI未新低(看涨)
    """

    divergences = []
    
    for
 i in range(window, len(df)):
        price_window = df['收盘'].iloc[i-window:i]
        rsi_window = df['rsi'].iloc[i-window:i]
        
        # 顶背离检测

        if
 df['收盘'].iloc[i] == price_window.max() and df['rsi'].iloc[i] < rsi_window.max():
            divergences.append({
                'date'
: df['日期'].iloc[i],
                'type'
: '顶背离',
                'signal'
: '看跌'
            })
        
        # 底背离检测

        elif
 df['收盘'].iloc[i] == price_window.min() and df['rsi'].iloc[i] > rsi_window.min():
            divergences.append({
                'date'
: df['日期'].iloc[i],
                'type'
: '底背离',
                'signal'
: '看涨'
            })
    
    return
 pd.DataFrame(divergences)

6.2 多周期RSI对比

# 计算不同周期的RSI
df['rsi_6'] = calculate_rsi(df, period=6)['rsi']   # 短期
df['rsi_14'] = calculate_rsi(df, period=14)['rsi'] # 中期
df['rsi_24'] = calculate_rsi(df, period=24)['rsi'] # 长期

# 多周期共振信号

# 当短期RSI上穿长期RSI时,买入信号更强

七、常见问题与注意事项

Q1: RSI参数设置多少合适?

  • • 短线交易:6-9日
  • • 中线交易:14日(默认,最常用)
  • • 长线投资:21-24日

Q2: RSI在单边行情中失效怎么办?

  • • 结合趋势指标(如MA、MACD)使用
  • • 调整超买超卖阈值(如80/20)
  • • 使用RSI背离信号

Q3: 如何提高RSI准确率?

  • • 多周期共振确认
  • • 结合成交量分析
  • • 配合支撑位/阻力位使用

八、下节预告

下一期我们将学习: 《Python量化实战:用TA-Lib一键计算多种技术指标》

  • • TA-Lib库介绍与安装
  • • 一键计算MACD、RSI、KDJ、布林带等
  • • 技术指标组合策略
  • • 实战回测框架搭建

完整代码已整理,复制即可运行。建议动手实践,遇到问题欢迎在评论区交流!

本文代码基于Python 3.8+,AKShare 1.15+,Pandas 2.0+环境测试通过。

                 

最新文章

随机文章